File indexing completed on 2024-05-12 05:17:20
0001 /* 0002 Copyright (C) 2009 Andras Mantia <amantia@kde.org> 0003 0004 Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0005 Author: Kevin Ottens <kevin@kdab.com> 0006 0007 This program is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This program is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with this program; if not, write to the Free Software 0019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include <qtest.h> 0023 0024 #include "kimap2test/fakeserver.h" 0025 #include "kimap2/session.h" 0026 #include "kimap2/loginjob.h" 0027 0028 #include <QtTest> 0029 0030 class LoginJobTest: public QObject 0031 { 0032 Q_OBJECT 0033 0034 private Q_SLOTS: 0035 0036 void shouldHandleLogin_data() 0037 { 0038 QTest::addColumn<QString>("user"); 0039 QTest::addColumn<QString>("password"); 0040 QTest::addColumn< QList<QByteArray> >("scenario"); 0041 0042 QList<QByteArray> scenario; 0043 scenario << FakeServer::greeting() 0044 << "C: A000001 CAPABILITY" 0045 << "S: A000001 OK" 0046 << "C: A000002 LOGIN \"user\" \"password\"" 0047 << "S: A000002 OK User logged in"; 0048 0049 QTest::newRow("success") << "user" << "password" << scenario; 0050 0051 scenario.clear(); 0052 scenario << FakeServer::greeting() 0053 << "C: A000001 CAPABILITY" 0054 << "S: A000001 OK" 0055 << "C: A000002 LOGIN \"user_bad\" \"password\"" 0056 << "S: A000002 NO Login failed: authentication failure"; 0057 0058 QTest::newRow("wrong login") << "user_bad" << "password" << scenario; 0059 0060 scenario.clear(); 0061 scenario << FakeServer::greeting() 0062 << "C: A000001 CAPABILITY" 0063 << "S: A000001 OK" 0064 << "C: A000002 LOGIN \"user\" \"aa\\\"bb\\\\cc[dd ee\"" 0065 << "S: A000002 OK User logged in"; 0066 0067 QTest::newRow("special chars") << "user" << "aa\"bb\\cc[dd ee" << scenario; 0068 0069 scenario.clear(); 0070 scenario << FakeServer::preauth(); 0071 0072 QTest::newRow("already authenticated") << "user" << "password" << scenario; 0073 } 0074 0075 void shouldHandleLogin() 0076 { 0077 QFETCH(QString, user); 0078 QFETCH(QString, password); 0079 QFETCH(QList<QByteArray>, scenario); 0080 0081 FakeServer fakeServer; 0082 fakeServer.setScenario(scenario); 0083 fakeServer.startAndWait(); 0084 0085 KIMAP2::Session *session = new KIMAP2::Session("127.0.0.1", 5989); 0086 0087 KIMAP2::LoginJob *login = new KIMAP2::LoginJob(session); 0088 login->setUserName(user); 0089 login->setPassword(password); 0090 bool result = login->exec(); 0091 0092 QEXPECT_FAIL("wrong login", "Login with bad user name", Continue); 0093 QEXPECT_FAIL("already authenticated", "Trying to log on an already authenticated session", Continue); 0094 QVERIFY(result); 0095 0096 fakeServer.quit(); 0097 delete session; 0098 } 0099 0100 void shouldHandleProxyLogin_data() 0101 { 0102 QTest::addColumn<QString>("user"); 0103 QTest::addColumn<QString>("proxy"); 0104 QTest::addColumn<QString>("password"); 0105 QTest::addColumn< QList<QByteArray> >("scenario"); 0106 0107 QList<QByteArray> scenario; 0108 scenario << FakeServer::greeting() 0109 << "C: A000001 CAPABILITY" 0110 << "S: A000001 OK" 0111 << "C: A000002 AUTHENTICATE PLAIN" 0112 << "S: A000002 OK (success)" 0113 << "C: A000003 LOGIN \"proxy\" \"user\" \"password\"" 0114 << "S: A000003 OK User logged in"; 0115 0116 QTest::newRow("success") << "user" << "proxy" << "password" << scenario; 0117 } 0118 0119 void shouldHandleProxyLogin() 0120 { 0121 QFETCH(QString, user); 0122 QFETCH(QString, proxy); 0123 QFETCH(QString, password); 0124 QFETCH(QList<QByteArray>, scenario); 0125 0126 FakeServer fakeServer; 0127 fakeServer.setScenario(scenario); 0128 fakeServer.startAndWait(); 0129 0130 KIMAP2::Session *session = new KIMAP2::Session("127.0.0.1", 5989); 0131 0132 KIMAP2::LoginJob *login = new KIMAP2::LoginJob(session); 0133 login->setAuthenticationMode(KIMAP2::LoginJob::Plain); 0134 login->setUserName(user); 0135 login->setAuthorizationName(proxy); 0136 login->setPassword(password); 0137 bool result = login->exec(); 0138 0139 QVERIFY(result); 0140 0141 fakeServer.quit(); 0142 delete session; 0143 } 0144 0145 void shouldSaveServerGreeting_data() 0146 { 0147 QTest::addColumn<QString>("greeting"); 0148 QTest::addColumn< QList<QByteArray> >("scenario"); 0149 0150 QList<QByteArray> scenario; 0151 scenario << FakeServer::greeting() 0152 << "C: A000001 CAPABILITY" 0153 << "S: A000001 OK" 0154 << "C: A000002 LOGIN \"user\" \"password\"" 0155 << "S: A000002 OK Welcome John Smith"; 0156 0157 QTest::newRow("greeting") << "Welcome John Smith" << scenario; 0158 0159 scenario.clear(); 0160 scenario << FakeServer::greeting() 0161 << "C: A000001 CAPABILITY" 0162 << "S: A000001 OK" 0163 << "C: A000002 LOGIN \"user\" \"password\"" 0164 << "S: A000002 OK Welcome John Smith (last login: Feb 21, 2010)"; 0165 0166 QTest::newRow("greeting with parenthesis") << "Welcome John Smith (last login: Feb 21, 2010)" << scenario; 0167 0168 scenario.clear(); 0169 scenario << FakeServer::greeting() 0170 << "C: A000001 CAPABILITY" 0171 << "S: A000001 OK" 0172 << "C: A000002 LOGIN \"user\" \"password\"" 0173 << "S: A000002 OK"; 0174 0175 QTest::newRow("no greeting") << "" << scenario; 0176 0177 scenario.clear(); 0178 scenario << FakeServer::greeting() 0179 << "C: A000001 CAPABILITY" 0180 << "S: A000001 OK" 0181 << "C: A000002 LOGIN \"user\" \"password\"" 0182 << "S: A000002 NO Login failed: authentication failure"; 0183 0184 QTest::newRow("login failed") << "" << scenario; 0185 } 0186 0187 void shouldSaveServerGreeting() 0188 { 0189 QFETCH(QString, greeting); 0190 QFETCH(QList<QByteArray>, scenario); 0191 0192 FakeServer fakeServer; 0193 fakeServer.setScenario(scenario); 0194 fakeServer.startAndWait(); 0195 0196 KIMAP2::Session *session = new KIMAP2::Session("127.0.0.1", 5989); 0197 0198 KIMAP2::LoginJob *login = new KIMAP2::LoginJob(session); 0199 login->setUserName("user"); 0200 login->setPassword("password"); 0201 login->exec(); 0202 0203 QCOMPARE(login->serverGreeting(), greeting); 0204 0205 fakeServer.quit(); 0206 delete session; 0207 } 0208 0209 void shouldUseSsl_data() 0210 { 0211 QTest::addColumn< QList<QByteArray> >("scenario"); 0212 QTest::addColumn< int >("serverEncryption"); 0213 QTest::addColumn< int >("clientEncryption"); 0214 QTest::addColumn< bool >("startTls"); 0215 0216 { 0217 QList<QByteArray> scenario; 0218 scenario << FakeServer::greeting() 0219 << "C: A000001 STARTTLS" 0220 << "S: A000001 OK" 0221 << "C: A000002 CAPABILITY" 0222 << "S: A000002 OK" 0223 << "C: A000003 LOGIN \"user\" \"password\"" 0224 << "S: A000003 OK"; 0225 0226 QTest::newRow("starttls tlsv1.0") << scenario << static_cast<int>(QSsl::TlsV1_0) << static_cast<int>(QSsl::TlsV1_0) << true; 0227 QTest::newRow("starttls tlsv1.1") << scenario << static_cast<int>(QSsl::TlsV1_1) << static_cast<int>(QSsl::TlsV1_1) << true; 0228 QTest::newRow("starttls tlsv1.2") << scenario << static_cast<int>(QSsl::TlsV1_2) << static_cast<int>(QSsl::TlsV1_2) << true; 0229 } 0230 { 0231 QList<QByteArray> scenario; 0232 scenario << FakeServer::greeting() 0233 << "C: A000001 CAPABILITY" 0234 << "S: A000001 OK" 0235 << "C: A000002 LOGIN \"user\" \"password\"" 0236 << "S: A000002 OK"; 0237 0238 //sslv3 is no longer supported by qsslsocket 0239 // QTest::newRow("sslv3") << scenario << static_cast<int>(QSsl::SslV3) << static_cast<int>(QSsl::SslV3) << false; 0240 //sslv2 is no longer supported by qsslsocket 0241 // QTest::newRow("sslv2") << scenario << static_cast<int>(QSsl::SslV2) << static_cast<int>(KIMAP2::LoginJob::SslV2); 0242 //AnyProtocol doesn't mean the server can force a specific version (e.g. openssl always starts with a sslv2 hello) 0243 QTest::newRow("any protocol with anyssl version") << scenario << static_cast<int>(QSsl::AnyProtocol) << static_cast<int>(QSsl::AnyProtocol) << false; 0244 QTest::newRow("tlsv1.0") << scenario << static_cast<int>(QSsl::TlsV1_0) << static_cast<int>(QSsl::TlsV1_0) << false; 0245 } 0246 } 0247 0248 void shouldUseSsl() 0249 { 0250 QSKIP("Test broken"); 0251 0252 QFETCH(QList<QByteArray>, scenario); 0253 QFETCH(int, serverEncryption); 0254 QFETCH(int, clientEncryption); 0255 QFETCH(bool, startTls); 0256 0257 FakeServer fakeServer; 0258 fakeServer.setEncrypted(static_cast<QSsl::SslProtocol>(serverEncryption), startTls); 0259 fakeServer.setScenario(scenario); 0260 fakeServer.startAndWait(); 0261 0262 KIMAP2::Session *session = new KIMAP2::Session("127.0.0.1", 5989); 0263 0264 QObject::connect(session, &KIMAP2::Session::sslErrors, [session](const QList<QSslError> &errors) { 0265 qWarning() << "Got ssl error: " << errors; 0266 session->ignoreErrors(errors); 0267 }); 0268 0269 KIMAP2::LoginJob *login = new KIMAP2::LoginJob(session); 0270 login->setUserName("user"); 0271 login->setPassword("password"); 0272 login->setEncryptionMode(static_cast<QSsl::SslProtocol>(clientEncryption), startTls); 0273 QVERIFY(login->exec()); 0274 0275 fakeServer.quit(); 0276 delete session; 0277 } 0278 0279 void shouldFailOnWrongSslSettings_data() 0280 { 0281 QTest::addColumn< QList<QByteArray> >("scenario"); 0282 QTest::addColumn< int >("serverEncryption"); 0283 QTest::addColumn< int >("clientEncryption"); 0284 QTest::addColumn< int >("expectedErrorCode"); 0285 0286 { 0287 QList<QByteArray> scenario; 0288 scenario << FakeServer::greeting(); 0289 0290 //For some reason only connecting to tlsv1 results in an ssl handshake error, with the wrong version only the server detects the error and disconnects 0291 // QTest::newRow( "ssl v3 v2" ) << scenario << static_cast<int>(QSsl::SslV3) << static_cast<int>(KIMAP2::LoginJob::SslV2) << static_cast<int>(KJob::UserDefinedError); 0292 QTest::newRow("ssl tlsv1 v3") << scenario << static_cast<int>(QSsl::SslV3) << static_cast<int>(QSsl::TlsV1_0) << static_cast<int>(KIMAP2::SslHandshakeFailed); 0293 } 0294 } 0295 0296 void shouldFailOnWrongSslSettings() 0297 { 0298 QFETCH(QList<QByteArray>, scenario); 0299 QFETCH(int, serverEncryption); 0300 Q_UNUSED(serverEncryption); 0301 QFETCH(int, clientEncryption); 0302 QFETCH(int, expectedErrorCode); 0303 0304 FakeServer fakeServer; 0305 fakeServer.setScenario(scenario); 0306 fakeServer.startAndWait(); 0307 0308 KIMAP2::Session *session = new KIMAP2::Session("127.0.0.1", 5989); 0309 0310 QObject::connect(session, &KIMAP2::Session::sslErrors, [session](const QList<QSslError> &errors) { 0311 qWarning() << "Got ssl error: " << errors; 0312 session->ignoreErrors(errors); 0313 }); 0314 0315 KIMAP2::LoginJob *login = new KIMAP2::LoginJob(session); 0316 login->setUserName("user"); 0317 login->setPassword("password"); 0318 login->setEncryptionMode(static_cast<QSsl::SslProtocol>(clientEncryption), false); 0319 QVERIFY(!login->exec()); 0320 QCOMPARE(static_cast<int>(login->error()), expectedErrorCode); 0321 0322 fakeServer.quit(); 0323 delete session; 0324 } 0325 0326 }; 0327 0328 QTEST_GUILESS_MAIN(LoginJobTest) 0329 0330 #include "loginjobtest.moc"