def test_add_and_delete_referrals(cfg, ipaddr): """ Test add and delete an LDAP referral with ManageDdsIT control. """ refdn = bonsai.LDAPDN("o=test-ref,ou=nerdherd,dc=bonsai,dc=test") ref = "ldap://test.host/cn=nobody" cli = LDAPClient("ldap://%s" % ipaddr) cli.set_credentials( "SIMPLE", user=cfg["SIMPLEAUTH"]["user"], password=cfg["SIMPLEAUTH"]["password"] ) cli.managedsait = True with cli.connect() as conn: entry = bonsai.LDAPEntry(refdn, conn) entry["objectClass"] = ["referral", "extensibleObject"] entry["o"] = "test-ref" entry["ref"] = ref conn.add(entry) res = conn.search(refdn, 0, attrlist=["ref"])[0] assert entry.dn == res.dn assert entry["ref"] == res["ref"] cli.managedsait = False with cli.connect() as conn: with pytest.raises(bonsai.LDAPError): conn.delete(entry.dn) cli.managedsait = True with cli.connect() as conn: conn.delete(entry.dn) res = conn.search(refdn, 0, attrlist=["ref"]) assert res == []
def test_password_modify_extop(conn, ipaddr): """ Test Password Modify extended operation. """ user_dn = LDAPDN("cn=skip,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % ipaddr) cli.set_credentials("SIMPLE", str(user_dn), "p@ssword") test_conn = cli.connect() with pytest.raises(TypeError): test_conn.modify_password(new_password=0) test_conn.modify_password(user_dn, "newpassword", "p@ssword") test_conn.close() with pytest.raises(ClosedConnection): test_conn.modify_password() try: cli.set_credentials("SIMPLE", str(user_dn), "newpassword") cli.set_password_policy(True) test_conn, ctrl = cli.connect() newpass = test_conn.modify_password() test_conn.close() assert isinstance(newpass, str) cli.set_credentials("SIMPLE", str(user_dn), newpass) test_conn, ctrl = cli.connect() test_conn.close() except bonsai.AuthenticationError: pytest.fail("Failed to authenticate with the new password.") finally: entry = conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry["userPassword"] = "******" entry.modify() entry = conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[ 0 ] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry["pwdChangeTime"] del entry["pwdGraceUseTime"] entry.modify()
def test_password_modify(self): """ Test modifing password with simple modify operation and password policy. """ if sys.platform == "win32": self.skipTest("Cannot use password policy on Windows") cli = LDAPClient(self.client.url) user_dn = "cn=jeff,ou=nerdherd,dc=bonsai,dc=test" cli.set_password_policy(True) cli.set_credentials("SIMPLE", (user_dn, "p@ssword")) conn, ctrl = cli.connect() entry = conn.search(user_dn, 0)[0] try: entry['userPassword'] = "******" entry.modify() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.PasswordModNotAllowed) user_dn = "cn=skip,ou=nerdherd,dc=bonsai,dc=test" cli.set_credentials("SIMPLE", (user_dn, "p@ssword")) conn, ctrl = cli.connect() entry = conn.search(user_dn, 0)[0] try: entry['userPassword'] = "******" entry.modify() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.PasswordTooShort) try: entry['userPassword'] = "******" entry.modify() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.PasswordInHistory)
def test_password_modify(client): """ Test modifying password with simple modify operation and password policy. """ cli = LDAPClient(client.url) user_dn = "cn=jeff,ou=nerdherd,dc=bonsai,dc=test" cli.set_password_policy(True) cli.set_credentials("SIMPLE", user_dn, "p@ssword") conn, _ = cli.connect() entry = conn.search(user_dn, 0)[0] try: entry["userPassword"] = "******" entry.modify() except Exception as exc: assert isinstance(exc, bonsai.errors.PasswordModNotAllowed) user_dn = "cn=skip,ou=nerdherd,dc=bonsai,dc=test" cli.set_credentials("SIMPLE", user_dn, "p@ssword") conn, _ = cli.connect() entry = conn.search(user_dn, 0)[0] try: entry["userPassword"] = "******" entry.modify() except Exception as exc: assert isinstance(exc, bonsai.errors.PasswordTooShort) try: entry["userPassword"] = "******" entry.modify() except Exception as exc: assert isinstance(exc, bonsai.errors.PasswordInHistory)
def test_password_modify_extop(self): """ Test Password Modify extended operation. """ user_dn = LDAPDN("cn=skip,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % self.ipaddr) cli.set_credentials("SIMPLE", (str(user_dn), "p@ssword")) conn = cli.connect() self.assertRaises(TypeError, lambda: conn.modify_password(new_password=0)) conn.modify_password(user_dn, "newpassword", "p@ssword") conn.close() self.assertRaises(ClosedConnection, conn.modify_password) try: cli.set_credentials("SIMPLE", (str(user_dn), "newpassword")) cli.set_password_policy(True) conn, ctrl = cli.connect() newpass = conn.modify_password() conn.close() self.assertIsInstance(newpass, str) cli.set_credentials("SIMPLE", (str(user_dn), newpass)) conn, ctrl = cli.connect() conn.close() except bonsai.AuthenticationError: self.fail("Failed to authenticate with the new password.") finally: entry = self.conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry['userPassword'] = "******" entry.modify() entry = self.conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry['pwdChangeTime'] del entry['pwdGraceUseTime'] entry.modify()
def test_password_expire(conn, ipaddr): """ Test password expiring with password policy. """ user_dn = "cn=skip,ou=nerdherd,dc=bonsai,dc=test" cli = LDAPClient("ldap://%s" % ipaddr) cli.set_password_policy(True) cli.set_credentials("SIMPLE", user_dn, "p@ssword") test_conn, ctrl = cli.connect() entry = test_conn.search(user_dn, 0)[0] entry["userPassword"] = "******" entry.modify() test_conn.close() cli.set_credentials("SIMPLE", user_dn, "newvalidpassword") time.sleep(2.0) test_conn, ctrl = cli.connect() if not (ctrl["expire"] <= 10 and ctrl["expire"] > 0): pytest.fail("Expire time is in the wrong range (Expire: %d)." % ctrl["expire"]) test_conn.close() time.sleep(10) test_conn, ctrl = cli.connect() assert ctrl["grace"] == 1 test_conn.close() with pytest.raises(bonsai.errors.PasswordExpired): test_conn, ctrl = cli.connect() entry = conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry["userPassword"] = "******" entry.modify() entry = conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry["pwdChangeTime"] del entry["pwdGraceUseTime"] entry.modify()
def test_password_modify_extop(conn, ipaddr): """ Test Password Modify extended operation. """ user_dn = LDAPDN("cn=skip,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % ipaddr) cli.set_credentials("SIMPLE", str(user_dn), "p@ssword") test_conn = cli.connect() with pytest.raises(TypeError): test_conn.modify_password(new_password=0) test_conn.modify_password(user_dn, "newpassword", "p@ssword") test_conn.close() with pytest.raises(ClosedConnection): test_conn.modify_password() try: cli.set_credentials("SIMPLE", str(user_dn), "newpassword") cli.set_password_policy(True) test_conn, ctrl = cli.connect() newpass = test_conn.modify_password() test_conn.close() assert isinstance(newpass, str) cli.set_credentials("SIMPLE", str(user_dn), newpass) test_conn, ctrl = cli.connect() test_conn.close() except bonsai.AuthenticationError: pytest.fail("Failed to authenticate with the new password.") finally: entry = conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry["userPassword"] = "******" entry.modify() entry = conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry["pwdChangeTime"] del entry["pwdGraceUseTime"] entry.modify()
def test_add_and_delete_referrals(cfg, ipaddr): """ Test add and delete an LDAP referral with ManageDdsIT control. """ refdn = bonsai.LDAPDN("o=test-ref,ou=nerdherd,dc=bonsai,dc=test") ref = "ldap://test.host/cn=nobody" cli = LDAPClient("ldap://%s" % ipaddr) cli.set_credentials("SIMPLE", user=cfg["SIMPLEAUTH"]["user"], password=cfg["SIMPLEAUTH"]["password"]) cli.managedsait = True with cli.connect() as conn: entry = bonsai.LDAPEntry(refdn, conn) entry["objectClass"] = ["referral", "extensibleObject"] entry["o"] = "test-ref" entry["ref"] = ref conn.add(entry) res = conn.search(refdn, 0, attrlist=["ref"])[0] assert entry.dn == res.dn assert entry["ref"] == res["ref"] cli.managedsait = False with cli.connect() as conn: with pytest.raises(bonsai.LDAPError): conn.delete(entry.dn) cli.managedsait = True with cli.connect() as conn: conn.delete(entry.dn) res = conn.search(refdn, 0, attrlist=["ref"]) assert res == []
def test_tls_timeout(url): """ Test TLS connection timeout. """ client = LDAPClient(url, True) client.set_cert_policy("ALLOW") client.set_ca_cert(None) client.set_ca_cert_dir(None) with network_delay(9.0): with pytest.raises(bonsai.TimeoutError): client.connect(timeout=5.0)
def test_search_with_managedsait_ctrl(ipaddr): """ Test searching with manageDsaIT control. """ refdn = LDAPDN("o=admin-ref,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % ipaddr) with cli.connect() as conn: res = conn.search(refdn, LDAPSearchScope.BASE, attrlist=["ref"])[0] assert str(res.dn) == "cn=admin,dc=bonsai,dc=test" cli.set_managedsait(True) with cli.connect() as conn: res = conn.search(refdn, LDAPSearchScope.BASE, attrlist=["ref"])[0] assert refdn == res.dn assert "ldap://bonsai.test/cn=admin,dc=bonsai,dc=test" == res["ref"][0]
def test_search_with_managedsait_ctrl(self): """ Test searching with manageDsaIT control. """ refdn = LDAPDN("o=admin-ref,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % self.ipaddr) with cli.connect() as conn: res = conn.search(refdn, LDAPSearchScope.BASE, attrlist=['ref'])[0] self.assertEqual(str(res.dn), "cn=admin,dc=bonsai,dc=test") cli.set_managedsait(True) with cli.connect() as conn: res = conn.search(refdn, LDAPSearchScope.BASE, attrlist=['ref'])[0] self.assertEqual(refdn, res.dn) self.assertEqual('ldap://bonsai.test/cn=admin,dc=bonsai,dc=test', res['ref'][0])
def test_referral_chasing(host_url): """ Testing referral chasing option. """ refdn = "o=admin,ou=nerdherd-refs,dc=bonsai,dc=test" client = LDAPClient(host_url) with client.connect() as conn: res = conn.search(refdn, 0) assert isinstance(res[0], bonsai.LDAPEntry) client.server_chase_referrals = False with client.connect() as conn: res = conn.search(refdn, 0) assert len(res) == 0 res = conn.search("ou=nerdherd-refs,dc=bonsai,dc=test", 1) refs = [item for item in res if isinstance(item, LDAPReference)] assert any(refs)
def test_bind_gssapi_keytab(cfg, ktpath): client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) client.set_credentials( "GSSAPI", user=cfg["GSSAPIAUTH"]["user"], realm=cfg["GSSAPIAUTH"]["realm"].upper(), keytab=ktpath, ) conn = client.connect() assert conn.whoami() == "dn:cn=chuck,ou=nerdherd,dc=bonsai,dc=test" client.set_credentials( "GSSAPI", user="******", realm=cfg["GSSAPIAUTH"]["realm"].upper(), keytab=ktpath ) conn = client.connect() assert conn.whoami() == "dn:cn=admin,dc=bonsai,dc=test"
def test_referral_chasing(self): """ Testing referral chasing option. """ refdn = "o=admin-ref,ou=nerdherd,dc=bonsai,dc=test" client = LDAPClient(self.url) conn = client.connect() res = conn.search(refdn, 0) self.assertIsInstance(res[0], bonsai.LDAPEntry) conn.close() client.server_chase_referrals = False conn = client.connect() res = conn.search(refdn, 0) self.assertEqual(len(res), 0) res = conn.search("ou=nerdherd,dc=bonsai,dc=test", 1) refs = [item for item in res if isinstance(item, LDAPReference)] self.assertTrue(any(refs))
def _bind_external(self, authzid): if 'EXTERNALAUTH' not in self.cfg: self.skipTest("EXTERNAL authentication is not set.") if sys.platform == "win32": self.skipTest("Windows relies on set certs in its cert store.") tls_impl = bonsai.get_tls_impl_name() if tls_impl == "GnuTLS" or tls_impl == "OpenSSL": curdir = os.path.abspath(os.path.dirname(__file__)) cert_path = os.path.join(curdir, 'testenv', 'certs') cli = LDAPClient(self.host, tls=True) cli.set_ca_cert(cert_path + '/cacert.pem') cli.set_client_cert(cert_path + '/client.pem') cli.set_client_key(cert_path + '/client.key') cli.set_credentials('EXTERNAL', (authzid,)) try: conn = cli.connect() except (bonsai.errors.ConnectionError, \ bonsai.errors.AuthenticationError): self.fail() else: self.assertNotEqual("anonymous", conn.whoami(), "EXTERNAL authentication was" " unsuccessful.") return conn else: self.skipTest("")
def _create_binding(auth, mech, authzid=None, realm=None): cfg = get_config() host = "ldap://%s" % cfg["SERVER"]["hostname"] client = LDAPClient(host) client.set_credentials(mech, cfg[auth]["user"], cfg[auth]["password"], realm, authzid) return client.connect()
def _create_kinit(authzid=None): try: cfg = get_config() user = cfg["GSSAPIAUTH"]["user"] password = cfg["GSSAPIAUTH"]["password"] proc = subprocess.Popen( ["kinit", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) output = " ".join(proc.communicate()) if "Heimdal" in output: # Heimdal Kerberos implementation. with tempfile.NamedTemporaryFile() as psw_tmp: psw_tmp.write(password.encode()) psw_tmp.flush() cmd = ["kinit", "--password-file=%s" % psw_tmp.name, user] subprocess.check_call(cmd) else: # MIT Kerberos implementation. cmd = 'echo "%s" | kinit %s' % (password, user) subprocess.check_output(cmd, shell=True) host = "ldap://%s" % cfg["SERVER"]["hostname"] client = LDAPClient(host) client.set_credentials( "GSSAPI", cfg["GSSAPIAUTH"]["user"], cfg["GSSAPIAUTH"]["password"], None, authzid, ) return client.connect() except subprocess.CalledProcessError: pytest.fail("Receiving TGT is failed.")
def _bind_external(self, authzid): if 'EXTERNALAUTH' not in self.cfg: self.skipTest("EXTERNAL authentication is not set.") if sys.platform == "win32": self.skipTest("Windows relies on set certs in its cert store.") tls_impl = bonsai.get_tls_impl_name() if tls_impl == "GnuTLS" or tls_impl == "OpenSSL": curdir = os.path.abspath(os.path.dirname(__file__)) cert_path = os.path.join(curdir, 'testenv', 'certs') cli = LDAPClient("ldap://%s" % self.cfg['SERVER']['hostname'], tls=True) cli.set_ca_cert(cert_path + '/cacert.pem') cli.set_client_cert(cert_path + '/client.pem') cli.set_client_key(cert_path + '/client.key') cli.set_credentials('EXTERNAL', (authzid, )) try: conn = cli.connect() except (bonsai.errors.ConnectionError, \ bonsai.errors.AuthenticationError): self.fail() else: self.assertNotEqual( "anonymous", conn.whoami(), "EXTERNAL authentication was" " unsuccessful.") return conn else: self.skipTest("")
def _create_binding(auth, mech, authzid=None, realm=None): cfg = get_config() host = "ldap://%s" % cfg["SERVER"]["hostname"] client = LDAPClient(host) client.set_credentials( mech, cfg[auth]["user"], cfg[auth]["password"], realm, authzid ) return client.connect()
def test_password_lockout(conn, ipaddr): """ Test password locking with password policy. """ user_dn = "cn=jeff,ou=nerdherd,dc=bonsai,dc=test" cli = LDAPClient("ldap://%s" % ipaddr) cli.set_password_policy(True) try: cli.set_credentials("SIMPLE", user_dn, "wrong_pass") test_conn, ctrl = cli.connect() except bonsai.errors.AuthenticationError: with pytest.raises(bonsai.errors.AccountLocked): cli.set_credentials("SIMPLE", user_dn, "p@ssword") test_conn, ctrl = cli.connect() finally: entry = conn.search(user_dn, 0, attrlist=["pwdAccountLockedTime"])[0] if "pwdAccountLockedTime" in entry.keys(): del entry["pwdAccountLockedTime"] entry.modify()
def test_bind_gssapi_keytab_error(cfg, ktpath): client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) client.set_credentials( "GSSAPI", user=cfg["GSSAPIAUTH"]["user"], realm=cfg["GSSAPIAUTH"]["realm"].upper(), keytab="invalid", ) with pytest.raises(bonsai.AuthenticationError): _ = client.connect() client.set_credentials( "GSSAPI", user="******", realm=cfg["GSSAPIAUTH"]["realm"].upper(), keytab=ktpath, ) with pytest.raises(bonsai.AuthenticationError): _ = client.connect()
def test_digest_auth_error(cfg): """ Test DIGEST-MD5 authentication error. """ client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) if cfg["DIGESTAUTH"]["realm"] == "None": realm = None else: realm = cfg["DIGESTAUTH"]["realm"].upper() client.set_credentials("DIGEST-MD5", cfg["DIGESTAUTH"]["user"], "wrongpassword", realm, None) with pytest.raises(bonsai.AuthenticationError): _ = client.connect()
def test_tls(url): """ Test TLS connection. """ client = LDAPClient(url, True) client.set_cert_policy("ALLOW") client.set_ca_cert(None) client.set_ca_cert_dir(None) try: conn = client.connect() conn.close() except Exception as exc: pytest.fail("TLS connection is failed with: %s" % str(exc))
def test_digest_auth_error(cfg): """ Test DIGEST-MD5 authentication error. """ client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) if cfg["DIGESTAUTH"]["realm"] == "None": realm = None else: realm = cfg["DIGESTAUTH"]["realm"].upper() client.set_credentials( "DIGEST-MD5", cfg["DIGESTAUTH"]["user"], "wrongpassword", realm, None ) with pytest.raises(bonsai.AuthenticationError): _ = client.connect()
def test_ldap_over_tls(ldaps_url): """ Test LDAP over TLS connection. """ client = LDAPClient(ldaps_url) client.set_cert_policy("ALLOW") client.set_ca_cert(None) client.set_ca_cert_dir(None) try: conn = client.connect() assert conn is not None conn.close() except Exception as exc: pytest.fail("TLS connection is failed with: %s" % str(exc))
def test_password_expire(self): """ Test password expiring with password policy. """ if sys.platform == "win32": self.skipTest("Cannot use password policy on Windows") user_dn = "cn=skip,ou=nerdherd,dc=bonsai,dc=test" cli = LDAPClient("ldap://%s" % self.ipaddr) cli.set_password_policy(True) cli.set_credentials("SIMPLE", (user_dn, "p@ssword")) conn, ctrl = cli.connect() entry = conn.search(user_dn, 0)[0] entry['userPassword'] = "******" entry.modify() conn.close() cli.set_credentials("SIMPLE", (user_dn, "newvalidpassword")) time.sleep(2.0) conn, ctrl = cli.connect() if not (ctrl['expire'] <= 10 and ctrl['expire'] > 0): self.fail("Expire time is in " "the wrong range (Expire: %d)." % ctrl['expire']) conn.close() time.sleep(10) conn, ctrl = cli.connect() self.assertEqual(ctrl['grace'], 1) conn.close() try: conn, ctrl = cli.connect() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.PasswordExpired) finally: entry = self.conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry['userPassword'] = "******" entry.modify() entry = self.conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry['pwdChangeTime'] del entry['pwdGraceUseTime'] entry.modify()
def test_digest_auth_error(self): """ Test DIGEST-MD5 authentication error. """ if "DIGESTAUTH" not in self.cfg: self.skipTest("No digest authentication is set.") client = LDAPClient(self.url) if self.cfg["DIGESTAUTH"]["realm"] == "None": realm = None else: realm = self.cfg["DIGESTAUTH"]["realm"] client.set_credentials("DIGEST-MD5", (self.cfg["DIGESTAUTH"]["user"], \ "wrongpassword", \ realm, None)) self.assertRaises(bonsai.AuthenticationError, lambda: client.connect())
def test_tls(self): """ Test TLS connection. """ if self.cfg['SERVER']['has_tls'] == 'False': self.skipTest("TLS is not set.") client = LDAPClient(self.url, True) client.set_cert_policy("ALLOW") client.set_ca_cert(None) client.set_ca_cert_dir(None) try: conn = client.connect() conn.close() except Exception as exc: self.fail("TLS connection is failed with: %s" % str(exc))
def test_password_modify_extop(self): """ Test Password Modify extended operation. """ if sys.platform == "win32": self.skipTest("Cannot use password modify extended opertion" " on Windows") user_dn = LDAPDN("cn=skip,ou=nerdherd,dc=bonsai,dc=test") cli = LDAPClient("ldap://%s" % self.ipaddr) cli.set_credentials("SIMPLE", (str(user_dn), "p@ssword")) conn = cli.connect() self.assertRaises(TypeError, lambda: conn.modify_password(new_password=0)) conn.modify_password(user_dn, "newpassword", "p@ssword") conn.close() self.assertRaises(ClosedConnection, lambda: conn.modify_password()) try: cli.set_credentials("SIMPLE", (str(user_dn), "newpassword")) cli.set_password_policy(True) conn, ctrl = cli.connect() newpass = conn.modify_password() conn.close() self.assertIsInstance(newpass, str) cli.set_credentials("SIMPLE", (str(user_dn), newpass)) conn, ctrl = cli.connect() conn.close() except bonsai.AuthenticationError: self.fail("Failed to authenticate with the new password.") finally: entry = self.conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry['userPassword'] = "******" entry.modify() entry = self.conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry['pwdChangeTime'] del entry['pwdGraceUseTime'] entry.modify()
def test_password_expire(self): """ Test password expiring with password policy. """ user_dn = "cn=skip,ou=nerdherd,dc=bonsai,dc=test" cli = LDAPClient("ldap://%s" % self.ipaddr) cli.set_password_policy(True) cli.set_credentials("SIMPLE", (user_dn, "p@ssword")) conn, ctrl = cli.connect() entry = conn.search(user_dn, 0)[0] entry['userPassword'] = "******" entry.modify() conn.close() cli.set_credentials("SIMPLE", (user_dn, "newvalidpassword")) time.sleep(2.0) conn, ctrl = cli.connect() if not (ctrl['expire'] <= 10 and ctrl['expire'] > 0): self.fail("Expire time is in " "the wrong range (Expire: %d)." % ctrl['expire']) conn.close() time.sleep(10) conn, ctrl = cli.connect() self.assertEqual(ctrl['grace'], 1) conn.close() try: conn, ctrl = cli.connect() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.PasswordExpired) finally: entry = self.conn.search(user_dn, 0, attrlist=["userPassword"])[0] entry['userPassword'] = "******" entry.modify() entry = self.conn.search(user_dn, 0, attrlist=["pwdChangeTime", "pwdGraceUseTime"])[0] if ("pwdChangeTime", "pwdGraceUseTime") in entry.keys(): del entry['pwdChangeTime'] del entry['pwdGraceUseTime'] entry.modify()
def test_paged_search_with_auto_acq(cfg, basedn): """ Test paged results control with automatic page acquiring. """ client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) conn = client.connect() search_dn = "ou=nerdherd,%s" % basedn res = conn.paged_search(search_dn, 1, page_size=3) if len(res) != 3: pytest.fail("The size of the page is not what is expected.") entry = 0 for ent in res: assert isinstance(ent, bonsai.LDAPEntry) entry += 1 assert entry == 6 assert res.acquire_next_page() is None
def test_paged_search_with_auto_acq(self): """ Test paged results control with automatic page acquiring. """ client = LDAPClient(self.url) conn = client.connect() search_dn = "ou=nerdherd,%s" % self.basedn res = conn.search(search_dn, 1, page_size=3) if len(res) != 3: self.fail("The size of the page is not what is expected.") entry = 0 for ent in res: self.assertIsInstance(ent, bonsai.LDAPEntry) entry += 1 self.assertEqual(entry, 6) self.assertIsNone(res.acquire_next_page())
def test_extended_dn(self): """ Test extended dn control. """ client = LDAPClient(self.url) self.assertRaises(TypeError, lambda: client.set_extended_dn("A")) self.assertRaises(ValueError, lambda: client.set_extended_dn(2)) client.extended_dn_format = 0 self.assertEqual(client.extended_dn_format, 0) conn = client.connect() root_dse = client.get_rootDSE() result = conn.search("ou=nerdherd,dc=bonsai,dc=test", 0)[0] if '1.2.840.113556.1.4.529' in root_dse['supportedControl']: self.assertIsNotNone(result.extended_dn) self.assertEqual(result.extended_dn.split(';')[-1], str(result.dn)) else: self.assertIsNone(result.extended_dn)
def _create_external(authzid=None): tls_impl = bonsai.get_tls_impl_name() if tls_impl == "GnuTLS" or tls_impl == "OpenSSL": cfg = get_config() curdir = os.path.abspath(os.path.dirname(__file__)) cert_path = os.path.join(curdir, "testenv", "certs") host = "ldap://%s" % cfg["SERVER"]["hostname"] cli = LDAPClient(host, tls=True) cli.set_ca_cert(cert_path + "/cacert.pem") cli.set_client_cert(cert_path + "/client.pem") cli.set_client_key(cert_path + "/client.key") cli.set_credentials("EXTERNAL", authz_id=authzid) return cli.connect() else: pytest.skip("")
def test_password_lockout(self): """ Test password locking with password policy. """ if sys.platform == "win32": self.skipTest("Cannot use password policy on Windows") user_dn = "cn=jeff,ou=nerdherd,dc=bonsai,dc=test" cli = LDAPClient("ldap://%s" % self.ipaddr) cli.set_password_policy(True) try: cli.set_credentials("SIMPLE", (user_dn, "wrong_pass")) conn, ctrl = cli.connect() except bonsai.errors.AuthenticationError: try: cli.set_credentials("SIMPLE", (user_dn, "p@ssword")) conn, ctrl = cli.connect() except Exception as exc: self.assertIsInstance(exc, bonsai.errors.AccountLocked) else: self.fail("No exception.") finally: entry = self.conn.search(user_dn, 0, attrlist=["pwdAccountLockedTime"])[0] if "pwdAccountLockedTime" in entry.keys(): del entry['pwdAccountLockedTime'] entry.modify()
def _binding(self, auth, mech, authzid, realm=None): if auth not in self.cfg: self.skipTest("%s authentication is not set." % mech) client = LDAPClient(self.host) client.set_credentials(mech, (self.cfg[auth]["user"], self.cfg[auth]["password"], realm, authzid)) try: conn = client.connect() except (bonsai.errors.ConnectionError, \ bonsai.errors.AuthenticationError) as err: self.fail(err) else: self.assertNotEqual("anonymous", conn.whoami(), "%s authentication was unsuccessful." % mech) return conn
def setUp(self): """ Set LDAP URL and open connection. """ curdir = os.path.abspath(os.path.dirname(__file__)) self.cfg = configparser.ConfigParser() self.cfg.read(os.path.join(curdir, 'test.ini')) self.url = "ldap://%s:%s/%s?%s?%s" % (self.cfg["SERVER"]["hostip"], \ self.cfg["SERVER"]["port"], \ self.cfg["SERVER"]["basedn"], \ self.cfg["SERVER"]["search_attr"], \ self.cfg["SERVER"]["search_scope"]) self.basedn = self.cfg["SERVER"]["basedn"] client = LDAPClient(self.url) client.set_credentials("SIMPLE", (self.cfg["SIMPLEAUTH"]["user"], self.cfg["SIMPLEAUTH"]["password"])) self.conn = client.connect() self.async_conn = LDAPConnection(client, True)
def _binding(self, auth, mech, authzid, realm=None): if auth not in self.cfg: self.skipTest("%s authentication is not set." % mech) client = LDAPClient(self.url) client.set_credentials(mech, (self.cfg[auth]["user"], self.cfg[auth]["password"], realm, authzid)) try: conn = client.connect() except (bonsai.errors.ConnectionError, \ bonsai.errors.AuthenticationError) as err: self.fail(err) else: self.assertNotEqual("anonymous", conn.whoami(), "%s authentication was unsuccessful." % mech) return conn
def test_modify_referrals(client): """ Test modifying an LDAP referral with ManageDdsIT control. """ refdn = bonsai.LDAPDN("o=invalid-ref,ou=nerdherd,dc=bonsai,dc=test") newref = "ldap://invalid.host/cn=nobody" cli = LDAPClient(client.url) cli.set_credentials(client.mechanism, **client.credentials) cli.managedsait = True with cli.connect() as conn: entry = LDAPEntry(refdn, conn) entry.change_attribute("ref", LDAPModOp.ADD, newref) entry.modify() res = conn.search(refdn, 0, attrlist=["ref"])[0] assert len(res["ref"]) == 3 assert newref in res["ref"] entry.change_attribute("ref", LDAPModOp.DELETE, newref) entry.modify()
def test_bind_gssapi_error(self): """ Test automatic TGT requesting with wrong realm name. """ if "GSSAPIAUTH" not in self.cfg: self.skipTest("GSSAPI authentication is not set.") if not bonsai.has_krb5_support(): self.skipTest("Module doesn't have KRB5 support.") if ("realm" not in self.cfg["GSSAPIAUTH"] or self.cfg["GSSAPIAUTH"]["realm"] == "None"): self.skipTest("Realm is not set.") client = LDAPClient(self.url) client.set_credentials("GSSAPI", (self.cfg["GSSAPIAUTH"]["user"], self.cfg["GSSAPIAUTH"]["password"], self.cfg["GSSAPIAUTH"]["realm"], None)) self.assertRaises(bonsai.AuthenticationError, lambda: client.connect())
def setUp(self): """ Set LDAP URL and open connection. """ curdir = os.path.abspath(os.path.dirname(__file__)) self.cfg = configparser.ConfigParser() self.cfg.read(os.path.join(curdir, 'test.ini')) self.ipaddr = self.cfg["SERVER"]["hostip"] self.url = "ldap://%s:%s/ou=nerdherd,%s?%s?%s" % \ (self.cfg["SERVER"]["hostip"], self.cfg["SERVER"]["port"], self.cfg["SERVER"]["basedn"], self.cfg["SERVER"]["search_attr"], self.cfg["SERVER"]["search_scope"]) self.host = "ldap://%s" % self.cfg['SERVER']['hostname'] self.basedn = self.cfg["SERVER"]["basedn"] client = LDAPClient(self.url) client.set_credentials("SIMPLE", (self.cfg["SIMPLEAUTH"]["user"], self.cfg["SIMPLEAUTH"]["password"])) self.conn = client.connect() self.async_conn = LDAPConnection(client, True)
def test_ppolicy(self): """ Test password policy setting. """ client = LDAPClient(self.url) self.assertRaises(TypeError, lambda: client.set_password_policy("F")) client.password_policy = True client.set_credentials("SIMPLE", ("cn=chuck,ou=nerdherd,dc=bonsai,dc=test", "p@ssword")) ret_val = client.connect() self.assertIsInstance(ret_val, tuple) self.assertIsInstance(ret_val[0], LDAPConnection) if ret_val[1] is None: pass elif type(ret_val[1]) == dict: self.assertIn("oid", ret_val[1].keys()) self.assertIn("expire", ret_val[1].keys()) self.assertIn("grace", ret_val[1].keys()) self.assertEqual('1.3.6.1.4.1.42.2.27.8.5.1', ret_val[1]['oid']) else: self.fail("Invalid second object in the tuple.") ret_val[0].close()
def test_connection_error(self): """ Test connection error. """ client = LDAPClient("ldap://invalid") self.assertRaises(bonsai.ConnectionError, lambda: client.connect())
def test_simple_auth_error(self): """ Test simple authentication error. """ client = LDAPClient(self.url) client.set_credentials("SIMPLE", ("cn=wrong", "wronger")) self.assertRaises(bonsai.AuthenticationError, lambda: client.connect())
def test_simple_auth_error(cfg): """ Test simple authentication error. """ client = LDAPClient("ldap://%s" % cfg["SERVER"]["hostname"]) client.set_credentials("SIMPLE", "cn=wrong", "wronger") with pytest.raises(bonsai.AuthenticationError): _ = client.connect()
class TornadoLDAPConnectionTest(TestCaseClass): """ Test TornadoLDAPConnection object. """ def setUp(self): """ Set LDAP URL and open connection. """ curdir = os.path.abspath(os.path.dirname(__file__)) self.cfg = configparser.ConfigParser() self.cfg.read(os.path.join(curdir, 'test.ini')) self.url = "ldap://%s:%s/%s?%s?%s" % (self.cfg["SERVER"]["hostip"], \ self.cfg["SERVER"]["port"], \ self.cfg["SERVER"]["basedn"], \ self.cfg["SERVER"]["search_attr"], \ self.cfg["SERVER"]["search_scope"]) self.basedn = self.cfg["SERVER"]["basedn"] self.ipaddr = self.cfg["SERVER"]["hostip"] self.client = LDAPClient(self.url) self.client.set_credentials("SIMPLE", (self.cfg["SIMPLEAUTH"]["user"], self.cfg["SIMPLEAUTH"]["password"])) self.client.set_async_connection_class(TornadoLDAPConnection) self.io_loop = self.get_new_ioloop() @gen_test(timeout=20.0) def test_connection(self): conn = yield self.client.connect(True, ioloop=self.io_loop) self.assertIsNotNone(conn) self.assertFalse(conn.closed) conn.close() @gen_test(timeout=20.0) def test_search(self): with (yield self.client.connect(True, ioloop=self.io_loop)) as conn: res = yield conn.search() self.assertIsNotNone(res) @gen_test(timeout=20.0) def test_add_and_delete(self): with (yield self.client.connect(True, ioloop=self.io_loop)) as conn: entry = LDAPEntry("cn=async_test,%s" % self.basedn) entry['objectclass'] = ['top', 'inetOrgPerson', 'person', 'organizationalPerson'] entry['sn'] = "async_test" try: yield conn.add(entry) except bonsai.errors.AlreadyExists: yield conn.delete(entry.dn) yield conn.add(entry) except: self.fail("Unexcepected error.") res = yield conn.search() self.assertIn(entry, res) yield entry.delete() res = yield conn.search() self.assertNotIn(entry, res) @gen_test(timeout=20.0) def test_recursive_delete(self): org1 = bonsai.LDAPEntry("ou=testusers,%s" % self.basedn) org1.update({"objectclass" : ['organizationalUnit', 'top'], "ou" : "testusers"}) org2 = bonsai.LDAPEntry("ou=tops,ou=testusers,%s" % self.basedn) org2.update({"objectclass" : ['organizationalUnit', 'top'], "ou" : "tops"}) entry = bonsai.LDAPEntry("cn=tester,ou=tops,ou=testusers,%s" % self.basedn) entry.update({"objectclass" : ["top", "inetorgperson"], "cn" : "tester", "sn" : "example"}) try: with (yield self.client.connect(True, timeout=10.0, ioloop=self.io_loop)) as conn: yield conn.add(org1) yield conn.add(org2) yield conn.add(entry) try: yield conn.delete(org1.dn) except bonsai.LDAPError as exc: self.assertIsInstance(exc, bonsai.errors.NotAllowedOnNonleaf) yield conn.delete(org1.dn, recursive=True) res = yield conn.search(org1.dn, 2) self.assertListEqual(res, []) except bonsai.LDAPError as err: self.fail("Recursive delete is failed: %s" % err) @gen_test(timeout=20.0) def test_modify_and_rename(self): with (yield self.client.connect(True, ioloop=self.io_loop)) as conn: entry = LDAPEntry("cn=async_test,%s" % self.basedn) entry['objectclass'] = ['top', 'inetOrgPerson', 'person', 'organizationalPerson'] entry['sn'] = "async_test" oldname = "cn=async_test,%s" % self.basedn newname = "cn=async_test2,%s" % self.basedn res = yield conn.search(newname, 0) if res: yield res[0].delete() try: yield conn.add(entry) except bonsai.errors.AlreadyExists: yield conn.delete(entry.dn) yield conn.add(entry) except: self.fail("Unexcepected error.") entry['sn'] = "async_test2" yield entry.modify() yield entry.rename(newname) res = yield conn.search(entry.dn, 0, attrlist=['sn']) self.assertEqual(entry['sn'], res[0]['sn']) res = yield conn.search(oldname, 0) self.assertEqual(res, []) yield conn.delete(entry.dn) @gen_test(timeout=20.0) def test_obj_err(self): entry = LDAPEntry("cn=async_test,%s" % self.basedn) entry['cn'] = ['async_test'] try: with (yield self.client.connect(True,ioloop=self.io_loop)) as conn: yield conn.add(entry) except bonsai.errors.ObjectClassViolation: return except Exception as exc: self.fail("test_obj_err failed with %s" % exc) self.fail("test_obj_err failed without the right exception.") @gen_test(timeout=20.0) def test_whoami(self): """ Test whoami. """ with (yield self.client.connect(True, ioloop=self.io_loop)) as conn: obj = yield conn.whoami() expected_res = ["dn:%s" % self.cfg["SIMPLEAUTH"]["user"], self.cfg["SIMPLEAUTH"]["adusername"]] self.assertIn(obj, expected_res) @gen_test(timeout=12.0) def test_connection_timeout(self): import xmlrpc.client as rpc proxy = rpc.ServerProxy("http://%s:%d/" % (self.ipaddr, 8000)) proxy.set_delay(6.0) time.sleep(3.0) try: conn = yield self.client.connect(True, ioloop=self.io_loop, timeout=8.0) except Exception as exc: self.assertIsInstance(exc, gen.TimeoutError) else: self.fail("Failed to receive TimeoutError.") finally: proxy.remove_delay() @gen_test(timeout=18.0) def test_search_timeout(self): import xmlrpc.client as rpc with (yield self.client.connect(True, ioloop=self.io_loop)) as conn: proxy = rpc.ServerProxy("http://%s:%d/" % (self.ipaddr, 8000)) proxy.set_delay(5.1) time.sleep(3.0) try: res = yield conn.search(timeout=4.0) except Exception as exc: self.assertIsInstance(exc, gen.TimeoutError) else: self.fail("Failed to receive TimeoutError.") finally: proxy.remove_delay()