File indexing completed on 2025-01-26 04:52:12

0001 /*
0002   This file is part of libkdepim.
0003 
0004   SPDX-FileCopyrightText: 2004 Tobias Koenig <tokoe@kde.org>
0005 
0006   SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "testkldap.h"
0010 
0011 #include "ber.h"
0012 #include "ldapconnection.h"
0013 #include "ldapdn.h"
0014 #include "ldapoperation.h"
0015 #include "ldapsearch.h"
0016 #include "ldapserver.h"
0017 #include "ldapurl.h"
0018 #include "ldif.h"
0019 
0020 #include <QDebug>
0021 #include <QFile>
0022 #include <QTest>
0023 QTEST_MAIN(KLdapTest)
0024 
0025 KLdapTest::KLdapTest(QObject *parent)
0026     : QObject(parent)
0027 {
0028 }
0029 
0030 void KLdapTest::initTestCase()
0031 {
0032     /*
0033       Read in the connection details of an LDAP server to use for testing.
0034       You should copy the file testurl.txt.tmpl to testurl.txt and specify a url in this file.
0035       The specified server should not be a production server in case we break anything here.
0036       You have been warned!
0037     */
0038     const QString filename(QStringLiteral("testurl.txt"));
0039     QFile file(filename);
0040     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0041         QTextStream stream(&file);
0042         stream >> m_url;
0043         file.close();
0044     }
0045 
0046     m_search = new LdapSearch;
0047 }
0048 
0049 void KLdapTest::testBer()
0050 {
0051     Ber ber1;
0052     Ber ber2;
0053     Ber ber3;
0054     Ber ber4;
0055     Ber ber5;
0056     Ber ber6;
0057     Ber ber7;
0058     Ber bber;
0059 
0060     int ainteger;
0061     QByteArray aoctetString1;
0062     QByteArray aoctetString2;
0063     QByteArray aoctetString3;
0064     QList<QByteArray> alist1;
0065     QList<QByteArray> alist2;
0066 
0067     int binteger;
0068     QByteArray boctetString1;
0069     QByteArray boctetString2;
0070     QByteArray boctetString3;
0071     QList<QByteArray> blist1;
0072     QList<QByteArray> blist2;
0073 
0074     aoctetString1 = "KDE";
0075     aoctetString2 = "the";
0076     aoctetString3 = "next generation";
0077 
0078     alist1.append(aoctetString1);
0079     alist1.append(aoctetString2);
0080 
0081     alist2.append(aoctetString2);
0082     alist2.append(aoctetString3);
0083     alist2.append(aoctetString1);
0084 
0085     ainteger = 23543;
0086 
0087     ber1.printf(QStringLiteral("i"), ainteger);
0088     ber2.printf(QStringLiteral("o"), &aoctetString1);
0089     ber3.printf(QStringLiteral("O"), &aoctetString2);
0090     ber4.printf(QStringLiteral("s"), &aoctetString3);
0091     ber5.printf(QStringLiteral("{v}"), &alist1);
0092     ber6.printf(QStringLiteral("{V}"), &alist2);
0093     ber7.printf(QStringLiteral("oi{v}O"), &aoctetString1, ainteger, &alist2, &aoctetString2);
0094 
0095     // test integer:
0096     bber = ber1;
0097     bber.scanf(QStringLiteral("i"), &binteger);
0098     QCOMPARE(ainteger, binteger);
0099 
0100     // test octet strings:
0101     bber = ber2;
0102     bber.scanf(QStringLiteral("o"), &boctetString1);
0103     QCOMPARE(aoctetString1, boctetString1);
0104     bber = ber3;
0105     bber.scanf(QStringLiteral("o"), &boctetString2);
0106     QCOMPARE(aoctetString2, boctetString2);
0107     bber = ber4;
0108     bber.scanf(QStringLiteral("o"), &boctetString3);
0109     QCOMPARE(aoctetString3, boctetString3);
0110 
0111     // test sequence of octet strings:
0112     bber = ber5;
0113     bber.scanf(QStringLiteral("v"), &blist1);
0114     QCOMPARE(alist1, blist1);
0115 
0116     bber = ber6;
0117     bber.scanf(QStringLiteral("v"), &blist2);
0118     QCOMPARE(alist2, blist2);
0119 
0120     // complex tests
0121     boctetString1 = boctetString2 = boctetString3 = QByteArray();
0122     binteger = 0;
0123     blist1.clear();
0124     blist2.clear();
0125 
0126     bber = ber7;
0127     bber.scanf(QStringLiteral("oivO"), &boctetString1, &binteger, &blist2, &boctetString2);
0128     QCOMPARE(aoctetString1, boctetString1);
0129     QCOMPARE(aoctetString2, boctetString2);
0130     QCOMPARE(alist2, blist2);
0131     QCOMPARE(ainteger, binteger);
0132 }
0133 
0134 void KLdapTest::cleanupTestCase()
0135 {
0136     delete m_search;
0137 }
0138 
0139 void KLdapTest::testLdapUrl()
0140 {
0141     // Test LdapUrl using some hardwired values so that we know what to compare to
0142     LdapUrl url;
0143     bool critical;
0144 
0145     url.setUrl(
0146         QStringLiteral("ldap://cn=manager,dc=kde,dc=org:password@localhost:3999/"
0147                        "dc=kde,dc=org?cn,mail?sub?(objectClass=*)?x-dir=base"));
0148     url.parseQuery();
0149 
0150     QCOMPARE(url.userName(), QStringLiteral("cn=manager,dc=kde,dc=org"));
0151     QCOMPARE(url.password(), QStringLiteral("password"));
0152     QCOMPARE(url.dn(), LdapDN(QStringLiteral("dc=kde,dc=org")));
0153     QCOMPARE(url.scope(), LdapUrl::Sub);
0154     QCOMPARE(url.attributes().at(0), QStringLiteral("cn"));
0155     QCOMPARE(url.attributes().at(1), QStringLiteral("mail"));
0156     QCOMPARE(url.filter(), QStringLiteral("(objectClass=*)"));
0157     QCOMPARE(url.extension(QStringLiteral("x-dir"), critical), QStringLiteral("base"));
0158     QCOMPARE(url.query(), QStringLiteral("?cn,mail?sub??x-dir=base"));
0159     // For some reason the code removes the filter if it's (objectClass=*)...
0160     QCOMPARE(url.toString(),
0161              QStringLiteral("ldap://cn=manager,dc=kde,dc=org:password@localhost:3999/"
0162                             "dc=kde,dc=org??cn,mail?sub??x-dir=base"));
0163 
0164     // Now set a different filter
0165     url.setFilter(QStringLiteral("(objectclass=person)"));
0166     QCOMPARE(url.toDisplayString(),
0167              QStringLiteral("ldap://cn=manager,dc=kde,dc=org@localhost:3999/"
0168                             "dc=kde,dc=org??cn,mail?sub?%28objectclass%3Dperson%29?x-dir=base"));
0169     QCOMPARE(url.filter(), QStringLiteral("(objectclass=person)"));
0170 
0171     // And now a filter with non-ascii letters
0172     url.setFilter(QStringLiteral("(givenName=Valérie *)"));
0173     QCOMPARE(url.toDisplayString(),
0174              QString::fromUtf8("ldap://cn=manager,dc=kde,dc=org@localhost:3999/"
0175                                "dc=kde,dc=org??cn,mail?sub?%28givenName%3DValérie %2A%29?x-dir=base"));
0176     QCOMPARE(url.filter(), QStringLiteral("(givenName=Valérie *)"));
0177 
0178     // Test roundtrip via QUrl, as happens when sending it to kio_ldap
0179     const QUrl qurl(url);
0180     QCOMPARE(qurl.toDisplayString(), url.toDisplayString());
0181 
0182     const LdapUrl kiourl(qurl);
0183     QCOMPARE(kiourl.toString(), url.toString());
0184     QCOMPARE(kiourl.toDisplayString(), url.toDisplayString());
0185     QCOMPARE(kiourl.filter(), QStringLiteral("(givenName=Valérie *)"));
0186 }
0187 
0188 void KLdapTest::testLdapConnection()
0189 {
0190     // Try to connect using an LdapUrl (read in from testurl.txt).
0191     LdapUrl url;
0192     url.setUrl(m_url);
0193 
0194     LdapConnection conn;
0195     conn.setUrl(url);
0196     int ret;
0197     if ((ret = conn.connect())) {
0198         qDebug() << "Could not connect to LDAP server. Error was:" << conn.connectionError();
0199     }
0200     QCOMPARE(ret, 0);
0201 
0202     LdapOperation op(conn);
0203     // Now attempt to bind
0204     if ((ret = op.bind_s())) {
0205         qDebug() << "Could not bind to server. Error was:" << conn.ldapErrorString();
0206     }
0207     QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
0208     QCOMPARE(ret, 0);
0209 }
0210 
0211 void KLdapTest::testLdapSearch()
0212 {
0213     // Lets try a search using the specified url
0214     LdapUrl url;
0215     url.setUrl(m_url);
0216     url.parseQuery();
0217     connect(m_search, &LdapSearch::result, this, &KLdapTest::searchResult);
0218     connect(m_search, &LdapSearch::data, this, &KLdapTest::searchData);
0219     const bool success = m_search->search(url);
0220     QCoreApplication::processEvents();
0221 
0222     QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
0223     QCOMPARE(success, true);
0224 
0225     qDebug() << "Search found" << m_objects.size() << "matching entries";
0226 }
0227 
0228 void KLdapTest::searchResult(KLDAPCore::LdapSearch *search)
0229 {
0230     qDebug();
0231     const int err = search->error();
0232     if (err) {
0233         qDebug() << "Search returned the following error:" << search->errorString();
0234     }
0235     QCOMPARE(err, 0);
0236 }
0237 
0238 void KLdapTest::searchData(KLDAPCore::LdapSearch *search, const KLDAPCore::LdapObject &obj)
0239 {
0240     Q_UNUSED(search)
0241     // qDebug();
0242     // qDebug() << "Object:";
0243     // qDebug() << obj.toString();
0244     m_objects.append(obj);
0245 }
0246 
0247 void KLdapTest::testLdapDN()
0248 {
0249     const QString strDN(QStringLiteral("uid=Test\\+Person+ou=accounts\\,outgoing,dc=kde,dc=org"));
0250     const LdapDN dn(strDN);
0251     QCOMPARE(dn.isValid(), true);
0252     QCOMPARE(dn.rdnString(), QStringLiteral("uid=Test\\+Person+ou=accounts\\,outgoing"));
0253 }
0254 
0255 void KLdapTest::testLdapModel()
0256 {
0257     // Use the user-supplied testing url
0258     LdapUrl url;
0259     url.setUrl(m_url);
0260 
0261     // Create a connection to use and bind with it
0262     LdapConnection conn;
0263     conn.setUrl(url);
0264     int ret;
0265     if ((ret = conn.connect())) {
0266         qDebug() << "Could not connect to LDAP server. Error was:" << conn.connectionError();
0267     }
0268     QCOMPARE(ret, 0);
0269 
0270     LdapOperation op(conn);
0271     if ((ret = op.bind_s())) {
0272         qDebug() << "Could not bind to server. Error was:" << conn.ldapErrorString();
0273     }
0274     QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
0275     QCOMPARE(ret, 0);
0276 
0277     QCoreApplication::processEvents();
0278 }
0279 
0280 /*
0281   void KLdapTest::testKLdap()
0282   {
0283   LdapUrl url;
0284   bool critical;
0285 
0286   url.setUrl("ldap://cn=manager,dc=kde,dc=org:password@localhost:3999"
0287              "/dc=kde,dc=org?cn,mail?sub?(objectClass=*)?x-dir=base");
0288   url.parseQuery();
0289 
0290   QCOMPARE( url.user(), QStringLiteral("cn=manager,dc=kde,dc=org") );
0291   QCOMPARE( url.password(), QStringLiteral("password") );
0292   QCOMPARE( url.dn(), QStringLiteral("dc=kde,dc=org") );
0293   QCOMPARE( url.scope(), LdapUrl::Sub );
0294   QCOMPARE( url.attributes().at(0), QStringLiteral("cn") );
0295   QCOMPARE( url.attributes().at(1), QStringLiteral("mail") );
0296   QCOMPARE( url.filter(), QStringLiteral("(objectClass=*)") );
0297   QCOMPARE( url.extension(QStringLiteral("x-dir"), critical), QStringLiteral("base") );
0298 
0299   url.setDn("ou=People,dc=kde,dc=org");
0300   QCOMPARE( url.dn(), QStringLiteral("ou=People,dc=kde,dc=org") );
0301   url.setDn("/ou=People,dc=kde,dc=org");
0302   QCOMPARE( url.dn(), QStringLiteral("ou=People,dc=kde,dc=org") );
0303 
0304   LdapServer server;
0305 //  url.setUrl("ldaps://cn=manager,dc=kde,dc=org:passwor@localhost:3999/"
0306                "dc=kde,dc=org????x-timelimt=5,x-sizelimit=6,x=pagesize=7,binddn=cn=apple,ou=berry");
0307 url.setUrl("ldaps://cn=manager,dc=kde,dc=org:password@localhost:3999/"
0308            "dc=kde,dc=org??base??x-timelimit=5");
0309 url.parseQuery();
0310 server.setUrl( url );
0311 QCOMPARE( url.query(), QStringLiteral("??base??x-timelimit=5") );
0312 QCOMPARE( url.url(), server.url().url() );
0313 
0314 LdapControl c1;
0315 c1.setControl( QStringLiteral("1.2.3.4.5.6"), QByteArray("abcdefg"), true );
0316 //test copy constructor
0317 LdapControl c2(c1);
0318 QCOMPARE( c2.oid(), QStringLiteral("1.2.3.4.5.6") );
0319 QCOMPARE( c2.value(), QByteArray("abcdefg") );
0320 QCOMPARE( c2.critical(), true );
0321 //test assignment operator
0322 LdapControl c3;
0323 c3 = c1;
0324 QCOMPARE( c3.oid(), QStringLiteral("1.2.3.4.5.6") );
0325 QCOMPARE( c3.value(), QByteArray("abcdefg") );
0326 QCOMPARE( c3.critical(), true );
0327 */
0328 // test Ber functions
0329 /*
0330   QByteArray left1("bertest"), right1;
0331   int left2 = 0, right2;
0332   int left3 = 1, right3;
0333   int left4 = 2, right4;
0334   int left5 = 3, right5;
0335   int left6 = 1, right6;
0336   QList<QByteArray> left7, right7;
0337   left7.append( "abcdefghij" );
0338   left7.append( "123456789" );
0339   left7.append( "1234\0\0\056789" );
0340 
0341   Ber ber;
0342   ber.printf("{seeiib}", &left1, left2, left3, left4, left5, left6 );
0343 
0344 //  ber.printf("{ioOi{i}}", left3, &left1, &left2, left4, left4 );
0345 Ber ber2 = ber;
0346 
0347 unsigned int a;
0348 int b;
0349 a = ber2.skipTag( b );
0350 qDebug() << "next tag:" << a << "size:" << b;
0351 a = ber2.skipTag( b );
0352 qDebug() << "next tag:" << a << "size:" << b;
0353 a = ber2.skipTag( b );
0354 qDebug() << "next tag:" << a << "size:" << b;
0355 a = ber2.skipTag( b );
0356 qDebug() << "next tag:" << a << "size:" << b;
0357 a = ber2.skipTag( b );
0358 qDebug() << "next tag:" << a << "size:" << b;
0359 a = ber2.skipTag( b );
0360 qDebug() << "next tag:" << a << "size:" << b;
0361 a = ber2.skipTag( b );
0362 qDebug() << "next tag:" << a << "size:" << b;
0363 a = ber2.skipTag( b );
0364 qDebug() << "next tag:" << a << "size:" << b;
0365 
0366 BerElement *_ber, *_ber2;
0367 _ber = ber_alloc_t( LBER_USE_DER );
0368 
0369 ber_len_t bl;
0370 ber_printf( _ber, "{i}", 5 );
0371 qDebug() << "native";
0372 _ber2 = ber_dup( _ber );
0373 a = ber_skip_tag( _ber2, &bl );
0374 qDebug() << "next tag:" << a << "size:" << bl;
0375 //  ber_dump( _ber, 0 );
0376 
0377 //  ber2.scanf("{v}", &right5 );
0378 
0379 //  ber2.scanf("{inoOi{v}}", &right3, &right1, &right2, &right4, &right5 );
0380 
0381 //  QCOMPARE( left1, right1 );
0382 //  QCOMPARE( left2, right2 );
0383 //  QCOMPARE( left3, right3 );
0384 //  QCOMPARE( left4, right4 );
0385 //  QCOMPARE( left5, right5 );
0386 */
0387 /*
0388   url.setUrl("ldap://localhost/dc=gyurco,dc=localdomain");
0389   url.parseQuery();
0390   server.setUrl( url );
0391   LdapConnection conn( server );
0392   int result = conn.connect();
0393   qDebug() << "connect result" << result << conn.errorString();
0394 
0395   LdapOperation op( conn );
0396   int msgid = op.search( "ou=People,dc=gyurco,dc=localdomain", LdapUrl::One, "", QStringList() );
0397   qDebug() << "search msgid" << msgid;
0398   result = op.result( msgid );
0399   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0400   while ( result == LdapOperation::RES_SEARCH_ENTRY ) {
0401   qDebug() << op.object().toString();
0402   result = op.result( msgid );
0403   }
0404   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0405 
0406   msgid = op.del( "ou=People,dc=gyurco,dc=localdomain" );
0407   qDebug() << "search msgid" << msgid;
0408   result = op.result( msgid );
0409   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0410 
0411   msgid = op.compare( "ou=People,dc=gyurco,dc=localdomain", "objectClass", QByteArray("top") );
0412   qDebug() << "search msgid" << msgid;
0413   result = op.result( msgid );
0414   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0415 
0416   msgid = op.compare( "ou=People,dc=gyurco,dc=localdomain", "objectClass",
0417                       QByteArray("inetOrgPerson") );
0418   qDebug() << "search msgid" << msgid;
0419   result = op.result( msgid );
0420   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0421 
0422   msgid = op.exop( "1.2.3.4.5.6.7.8", QByteArray("inetOrgPerson") );
0423   qDebug() << "search msgid" << msgid;
0424   result = op.result( msgid );
0425   qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
0426 */
0427 /*
0428   }
0429 */
0430 
0431 #include "moc_testkldap.cpp"