class PyCredentialsTests(TestCase): def setUp(self): super(PyCredentialsTests, self).setUp() self.server = os.environ["SERVER"] self.domain = os.environ["DOMAIN"] self.host = os.environ["SERVER_IP"] self.lp = self.get_loadparm() self.credentials = self.get_credentials() self.session = system_session() self.ldb = SamDB(url="ldap://%s" % self.host, session_info=self.session, credentials=self.credentials, lp=self.lp) self.create_machine_account() self.create_user_account() def tearDown(self): super(PyCredentialsTests, self).tearDown() delete_force(self.ldb, self.machine_dn) delete_force(self.ldb, self.user_dn) # Until a successful netlogon connection has been established there will # not be a valid authenticator associated with the credentials # and new_client_authenticator should throw a ValueError def test_no_netlogon_connection(self): self.assertRaises(ValueError, self.machine_creds.new_client_authenticator) # Once a netlogon connection has been established, # new_client_authenticator should return a value # def test_have_netlogon_connection(self): c = self.get_netlogon_connection() a = self.machine_creds.new_client_authenticator() self.assertIsNotNone(a) # Get an authenticator and use it on a sequence of operations requiring # an authenticator def test_client_authenticator(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonSamLogonWithFlags(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) def test_SamLogonEx(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise def test_SamLogonEx_no_domain(self): c = self.get_netlogon_connection() self.user_creds.set_domain('') logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: self.fail("got unexpected error" + str(e)) def test_SamLogonExNTLM(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds, flags=CLI_CRED_NTLM_AUTH) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise def test_SamLogonExMSCHAPv2(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds, flags=CLI_CRED_NTLM_AUTH) logon.identity_info.parameter_control = MSV1_0_ALLOW_MSVCHAPV2 logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise # Test Credentials.encrypt_netr_crypt_password # By performing a NetrServerPasswordSet2 # And the logging on using the new password. def test_encrypt_netr_password(self): # Change the password self.do_Netr_ServerPasswordSet2() # Now use the new password to perform an operation srvsvc.srvsvc("ncacn_np:%s" % (self.server), self.lp, self.machine_creds) # Change the current machine account password with a # netr_ServerPasswordSet2 call. def do_Netr_ServerPasswordSet2(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) PWD_LEN = 32 DATA_LEN = 512 newpass = samba.generate_random_password(PWD_LEN, PWD_LEN) encoded = newpass.encode('utf-16-le') pwd_len = len(encoded) filler = [x if isinstance(x, int) else ord(x) for x in os.urandom(DATA_LEN - pwd_len)] pwd = netlogon.netr_CryptPassword() pwd.length = pwd_len pwd.data = filler + [x if isinstance(x, int) else ord(x) for x in encoded] self.machine_creds.encrypt_netr_crypt_password(pwd) c.netr_ServerPasswordSet2(self.server, self.machine_creds.get_workstation(), SEC_CHAN_WKSTA, self.machine_name, authenticator, pwd) self.machine_pass = newpass self.machine_creds.set_password(newpass) # Establish sealed schannel netlogon connection over TCP/IP # def get_netlogon_connection(self): return netlogon.netlogon("ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, self.machine_creds) # # Create the machine account def create_machine_account(self): self.machine_pass = samba.generate_random_password(32, 32) self.machine_name = MACHINE_NAME self.machine_dn = "cn=%s,%s" % (self.machine_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.machine_dn) utf16pw = ('"%s"' % get_string(self.machine_pass)).encode('utf-16-le') self.ldb.add({ "dn": self.machine_dn, "objectclass": "computer", "sAMAccountName": "%s$" % self.machine_name, "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), "unicodePwd": utf16pw}) self.machine_creds = Credentials() self.machine_creds.guess(self.get_loadparm()) self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) self.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) self.machine_creds.set_password(self.machine_pass) self.machine_creds.set_username(self.machine_name + "$") self.machine_creds.set_workstation(self.machine_name) # # Create a test user account def create_user_account(self): self.user_pass = samba.generate_random_password(32, 32) self.user_name = USER_NAME self.user_dn = "cn=%s,%s" % (self.user_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.user_dn) utf16pw = ('"%s"' % get_string(self.user_pass)).encode('utf-16-le') self.ldb.add({ "dn": self.user_dn, "objectclass": "user", "sAMAccountName": "%s" % self.user_name, "userAccountControl": str(UF_NORMAL_ACCOUNT), "unicodePwd": utf16pw}) self.user_creds = Credentials() self.user_creds.guess(self.get_loadparm()) self.user_creds.set_password(self.user_pass) self.user_creds.set_username(self.user_name) self.user_creds.set_workstation(self.machine_name) pass # # Get the authenticator from the machine creds. def get_authenticator(self, c): auth = self.machine_creds.new_client_authenticator() current = netr_Authenticator() current.cred.data = [x if isinstance(x, int) else ord(x) for x in auth["credential"]] current.timestamp = auth["timestamp"] subsequent = netr_Authenticator() return (current, subsequent) def do_NetrLogonSamLogonWithFlags(self, c, current, subsequent): logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 c.netr_LogonSamLogonWithFlags(self.server, self.user_creds.get_workstation(), current, subsequent, logon_level, logon, validation_level, netr_flags) def do_NetrLogonGetDomainInfo(self, c, current, subsequent): query = netr_WorkstationInformation() c.netr_LogonGetDomainInfo(self.server, self.user_creds.get_workstation(), current, subsequent, 2, query)
class PyCredentialsTests(TestCase): def setUp(self): super(PyCredentialsTests, self).setUp() self.server = os.environ["SERVER"] self.domain = os.environ["DOMAIN"] self.host = os.environ["SERVER_IP"] self.lp = self.get_loadparm() self.credentials = self.get_credentials() self.session = system_session() self.ldb = SamDB(url="ldap://%s" % self.host, session_info=self.session, credentials=self.credentials, lp=self.lp) self.create_machine_account() self.create_user_account() def tearDown(self): super(PyCredentialsTests, self).tearDown() delete_force(self.ldb, self.machine_dn) delete_force(self.ldb, self.user_dn) # Until a successful netlogon connection has been established there will # not be a valid authenticator associated with the credentials # and new_client_authenticator should throw a ValueError def test_no_netlogon_connection(self): self.assertRaises(ValueError, self.machine_creds.new_client_authenticator) # Once a netlogon connection has been established, # new_client_authenticator should return a value # def test_have_netlogon_connection(self): c = self.get_netlogon_connection() a = self.machine_creds.new_client_authenticator() self.assertIsNotNone(a) # Get an authenticator and use it on a sequence of operations requiring # an authenticator def test_client_authenticator(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonSamLogonWithFlags(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) # Test Credentials.encrypt_netr_crypt_password # By performing a NetrServerPasswordSet2 # And the logging on using the new password. def test_encrypt_netr_password(self): # Change the password self.do_Netr_ServerPasswordSet2() # Now use the new password to perform an operation self.do_DsrEnumerateDomainTrusts() # Change the current machine account pazssword with a # netr_ServerPasswordSet2 call. def do_Netr_ServerPasswordSet2(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) PWD_LEN = 32 DATA_LEN = 512 newpass = samba.generate_random_password(PWD_LEN, PWD_LEN) filler = [ord(x) for x in os.urandom(DATA_LEN - PWD_LEN)] pwd = netlogon.netr_CryptPassword() pwd.length = PWD_LEN pwd.data = filler + [ord(x) for x in newpass] self.machine_creds.encrypt_netr_crypt_password(pwd) c.netr_ServerPasswordSet2(self.server, self.machine_creds.get_workstation(), SEC_CHAN_WKSTA, self.machine_name, authenticator, pwd) self.machine_pass = newpass self.machine_creds.set_password(newpass) # Perform a DsrEnumerateDomainTrusts, this provides confirmation that # a netlogon connection has been correctly established def do_DsrEnumerateDomainTrusts(self): c = self.get_netlogon_connection() trusts = c.netr_DsrEnumerateDomainTrusts( self.server, netlogon.NETR_TRUST_FLAG_IN_FOREST | netlogon.NETR_TRUST_FLAG_OUTBOUND | netlogon.NETR_TRUST_FLAG_INBOUND) # Establish sealed schannel netlogon connection over TCP/IP # def get_netlogon_connection(self): return netlogon.netlogon( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, self.machine_creds) # # Create the machine account def create_machine_account(self): self.machine_pass = samba.generate_random_password(32, 32) self.machine_name = MACHINE_NAME self.machine_dn = "cn=%s,%s" % (self.machine_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.machine_dn) utf16pw = unicode('"' + self.machine_pass.encode('utf-8') + '"', 'utf-8').encode('utf-16-le') self.ldb.add({ "dn": self.machine_dn, "objectclass": "computer", "sAMAccountName": "%s$" % self.machine_name, "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), "unicodePwd": utf16pw }) self.machine_creds = Credentials() self.machine_creds.guess(self.get_loadparm()) self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) self.machine_creds.set_password(self.machine_pass) self.machine_creds.set_username(self.machine_name + "$") self.machine_creds.set_workstation(self.machine_name) # # Create a test user account def create_user_account(self): self.user_pass = samba.generate_random_password(32, 32) self.user_name = USER_NAME self.user_dn = "cn=%s,%s" % (self.user_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.user_dn) utf16pw = unicode('"' + self.user_pass.encode('utf-8') + '"', 'utf-8').encode('utf-16-le') self.ldb.add({ "dn": self.user_dn, "objectclass": "user", "sAMAccountName": "%s" % self.user_name, "userAccountControl": str(UF_NORMAL_ACCOUNT), "unicodePwd": utf16pw }) self.user_creds = Credentials() self.user_creds.guess(self.get_loadparm()) self.user_creds.set_password(self.user_pass) self.user_creds.set_username(self.user_name) self.user_creds.set_workstation(self.machine_name) pass # # Get the authenticator from the machine creds. def get_authenticator(self, c): auth = self.machine_creds.new_client_authenticator() current = netr_Authenticator() current.cred.data = [ord(x) for x in auth["credential"]] current.timestamp = auth["timestamp"] subsequent = netr_Authenticator() return (current, subsequent) def do_NetrLogonSamLogonWithFlags(self, c, current, subsequent): logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 c.netr_LogonSamLogonWithFlags(self.server, self.user_creds.get_workstation(), current, subsequent, logon_level, logon, validation_level, netr_flags) def do_NetrLogonGetDomainInfo(self, c, current, subsequent): query = netr_WorkstationInformation() c.netr_LogonGetDomainInfo(self.server, self.user_creds.get_workstation(), current, subsequent, 2, query)
class PyCredentialsTests(TestCase): def setUp(self): super(PyCredentialsTests, self).setUp() self.server = os.environ["SERVER"] self.domain = os.environ["DOMAIN"] self.host = os.environ["SERVER_IP"] self.lp = self.get_loadparm() self.credentials = self.get_credentials() self.session = system_session() self.ldb = SamDB(url="ldap://%s" % self.host, session_info=self.session, credentials=self.credentials, lp=self.lp) self.create_machine_account() self.create_user_account() def tearDown(self): super(PyCredentialsTests, self).tearDown() delete_force(self.ldb, self.machine_dn) delete_force(self.ldb, self.user_dn) # Until a successful netlogon connection has been established there will # not be a valid authenticator associated with the credentials # and new_client_authenticator should throw a ValueError def test_no_netlogon_connection(self): self.assertRaises(ValueError, self.machine_creds.new_client_authenticator) # Once a netlogon connection has been established, # new_client_authenticator should return a value # def test_have_netlogon_connection(self): c = self.get_netlogon_connection() a = self.machine_creds.new_client_authenticator() self.assertIsNotNone(a) # Get an authenticator and use it on a sequence of operations requiring # an authenticator def test_client_authenticator(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonSamLogonWithFlags(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) (authenticator, subsequent) = self.get_authenticator(c) self.do_NetrLogonGetDomainInfo(c, authenticator, subsequent) def test_SamLogonEx(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise def test_SamLogonEx_no_domain(self): c = self.get_netlogon_connection() self.user_creds.set_domain('') logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: self.fail("got unexpected error" + str(e)) def test_SamLogonExNTLM(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds, flags=CLI_CRED_NTLM_AUTH) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise def test_SamLogonExMSCHAPv2(self): c = self.get_netlogon_connection() logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds, flags=CLI_CRED_NTLM_AUTH) logon.identity_info.parameter_control = MSV1_0_ALLOW_MSVCHAPV2 logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 try: c.netr_LogonSamLogonEx(self.server, self.user_creds.get_workstation(), logon_level, logon, validation_level, netr_flags) except NTSTATUSError as e: enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_WRONG_PASSWORD: self.fail("got wrong password error") else: raise # Test Credentials.encrypt_netr_crypt_password # By performing a NetrServerPasswordSet2 # And the logging on using the new password. def test_encrypt_netr_password(self): # Change the password self.do_Netr_ServerPasswordSet2() # Now use the new password to perform an operation srvsvc.srvsvc("ncacn_np:%s" % (self.server), self.lp, self.machine_creds) # Change the current machine account password with a # netr_ServerPasswordSet2 call. def do_Netr_ServerPasswordSet2(self): c = self.get_netlogon_connection() (authenticator, subsequent) = self.get_authenticator(c) PWD_LEN = 32 DATA_LEN = 512 newpass = samba.generate_random_password(PWD_LEN, PWD_LEN) encoded = newpass.encode('utf-16-le') pwd_len = len(encoded) filler = [ord(x) for x in os.urandom(DATA_LEN-pwd_len)] pwd = netlogon.netr_CryptPassword() pwd.length = pwd_len pwd.data = filler + [ord(x) for x in encoded] self.machine_creds.encrypt_netr_crypt_password(pwd) c.netr_ServerPasswordSet2(self.server, self.machine_creds.get_workstation(), SEC_CHAN_WKSTA, self.machine_name, authenticator, pwd) self.machine_pass = newpass self.machine_creds.set_password(newpass) # Establish sealed schannel netlogon connection over TCP/IP # def get_netlogon_connection(self): return netlogon.netlogon("ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, self.machine_creds) # # Create the machine account def create_machine_account(self): self.machine_pass = samba.generate_random_password(32, 32) self.machine_name = MACHINE_NAME self.machine_dn = "cn=%s,%s" % (self.machine_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.machine_dn) utf16pw = unicode( '"' + self.machine_pass.encode('utf-8') + '"', 'utf-8' ).encode('utf-16-le') self.ldb.add({ "dn": self.machine_dn, "objectclass": "computer", "sAMAccountName": "%s$" % self.machine_name, "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), "unicodePwd": utf16pw}) self.machine_creds = Credentials() self.machine_creds.guess(self.get_loadparm()) self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) self.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) self.machine_creds.set_password(self.machine_pass) self.machine_creds.set_username(self.machine_name + "$") self.machine_creds.set_workstation(self.machine_name) # # Create a test user account def create_user_account(self): self.user_pass = samba.generate_random_password(32, 32) self.user_name = USER_NAME self.user_dn = "cn=%s,%s" % (self.user_name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, self.user_dn) utf16pw = unicode( '"' + self.user_pass.encode('utf-8') + '"', 'utf-8' ).encode('utf-16-le') self.ldb.add({ "dn": self.user_dn, "objectclass": "user", "sAMAccountName": "%s" % self.user_name, "userAccountControl": str(UF_NORMAL_ACCOUNT), "unicodePwd": utf16pw}) self.user_creds = Credentials() self.user_creds.guess(self.get_loadparm()) self.user_creds.set_password(self.user_pass) self.user_creds.set_username(self.user_name) self.user_creds.set_workstation(self.machine_name) pass # # Get the authenticator from the machine creds. def get_authenticator(self, c): auth = self.machine_creds.new_client_authenticator(); current = netr_Authenticator() current.cred.data = [ord(x) for x in auth["credential"]] current.timestamp = auth["timestamp"] subsequent = netr_Authenticator() return (current, subsequent) def do_NetrLogonSamLogonWithFlags(self, c, current, subsequent): logon = samlogon_logon_info(self.domain, self.machine_name, self.user_creds) logon_level = netlogon.NetlogonNetworkTransitiveInformation validation_level = netlogon.NetlogonValidationSamInfo4 netr_flags = 0 c.netr_LogonSamLogonWithFlags(self.server, self.user_creds.get_workstation(), current, subsequent, logon_level, logon, validation_level, netr_flags) def do_NetrLogonGetDomainInfo(self, c, current, subsequent): query = netr_WorkstationInformation() c.netr_LogonGetDomainInfo(self.server, self.user_creds.get_workstation(), current, subsequent, 2, query)