def negotiate_server(self): token = self._inner.read() self.client_ctx = gensec.Security.start_server(settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx)) # gssapi.SecurityContext(name=self.server_name, usage='initiate', # flags=self.flags) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.client_ctx.set_credentials(creds) self.client_ctx.start_mech_by_name("spnego") # token = b'' server_finished = False while not server_finished: log.debug('Doing step') server_finished, server_to_client = self.client_ctx.update(token) self._inner.write(server_to_client) if not server_finished: token = self._inner.read() else: log.debug('GSSAPI Handshake done') self._inner.write_handshake_done(server_to_client)
def test_gp_inf_ext_utf(self): logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ext = gp_inf_ext(logger, self.lp, machine_creds, store) test_data = '[Kerberos Policy]\nMaxTicketAge = 99\n' with NamedTemporaryFile() as f: with codecs.open(f.name, 'w', 'utf-16') as w: w.write(test_data) try: inf_conf = ext.read(f.name) except UnicodeDecodeError: self.fail('Failed to parse utf-16') self.assertIn('Kerberos Policy', inf_conf.keys(), 'Kerberos Policy was not read from the file') self.assertEquals(inf_conf.get('Kerberos Policy', 'MaxTicketAge'), '99', 'MaxTicketAge was not read from the file') with NamedTemporaryFile() as f: with codecs.open(f.name, 'w', 'utf-8') as w: w.write(test_data) inf_conf = ext.read(f.name) self.assertIn('Kerberos Policy', inf_conf.keys(), 'Kerberos Policy was not read from the file') self.assertEquals(inf_conf.get('Kerberos Policy', 'MaxTicketAge'), '99', 'MaxTicketAge was not read from the file')
def test_lsa_LookupSids3_without_schannel(self): machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c = lsa.lsarpc( "ncacn_ip_tcp:%s[seal]" % self.server, self.lp, machine_creds) sids = lsa.SidArray() sid = lsa.SidPtr() # Need a set x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray2() level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 with self.assertRaises(NTSTATUSError) as e: c.LookupSids3(sids, names, level, count, lookup_options, client_revision) if (e.exception.args[0] != NT_STATUS_ACCESS_DENIED): raise AssertionError("LookupSids3 without schannel must fail with ACCESS_DENIED")
def test_lsa_LookupNames4_without_schannel(self): machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c_normal = lsa.lsarpc( "ncacn_np:%s[seal]" % self.server, self.lp, machine_creds) username, domain = c_normal.GetUserName(None, None, None) sids = lsa.TransSidArray3() names = [username] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 with self.assertRaises(NTSTATUSError) as e: c_normal.LookupNames4(names, sids, level, count, lookup_options, client_revision) if (e.exception.args[0] != NT_STATUS_ACCESS_DENIED): raise AssertionError("LookupNames4 without schannel must fail with ACCESS_DENIED")
def test_join_records_can_update(self): dc_creds = Credentials() dc_creds.guess(self.join_ctx.lp) dc_creds.set_machine_account(self.join_ctx.lp) self.tkey_trans(creds=dc_creds) p = self.make_name_packet(dns.DNS_OPCODE_UPDATE) q = self.make_name_question(self.join_ctx.dnsdomain, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN) questions = [] questions.append(q) self.finish_name_packet(p, questions) updates = [] # Delete the old expected IPs IPs = samba.interface_ips(self.lp) for IP in IPs[1:]: if ":" in IP: r = dns.res_rec() r.name = self.join_ctx.dnshostname r.rr_type = dns.DNS_QTYPE_AAAA r.rr_class = dns.DNS_QCLASS_NONE r.ttl = 0 r.length = 0xffff rdata = IP else: r = dns.res_rec() r.name = self.join_ctx.dnshostname r.rr_type = dns.DNS_QTYPE_A r.rr_class = dns.DNS_QCLASS_NONE r.ttl = 0 r.length = 0xffff rdata = IP r.rdata = rdata updates.append(r) p.nscount = len(updates) p.nsrecs = updates mac = self.sign_packet(p, self.key_name) (response, response_p) = self.dns_transaction_udp(p, self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.verify_packet(response, response_p, mac) p = self.make_name_packet(dns.DNS_OPCODE_QUERY) questions = [] name = self.join_ctx.dnshostname q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN) questions.append(q) self.finish_name_packet(p, questions) (response, response_packet) = self.dns_transaction_tcp(p, host=self.server_ip) self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK) self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY) self.assertEquals(response.ancount, 1)
def test_process_group_policy(self): local_path = self.lp.cache_path('gpo_cache') guids = [ '{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}' ] gpofile = '%s/ADDOM.SAMBA.EXAMPLE.COM/POLICIES/%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF' logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_sec_ext(logger, self.lp, machine_creds, store) ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) stage = '[Kerberos Policy]\nMaxTicketAge = %d\n' opts = [100, 200] for i in range(0, 2): gpttmpl = gpofile % (local_path, guids[i]) ret = stage_file(gpttmpl, stage % opts[i]) self.assertTrue(ret, 'Could not create the target %s' % gpttmpl) # Process all gpos ext.process_group_policy([], gpos) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, opts[1], 'Higher priority policy was not set') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, None, 'MaxTicketAge should not have applied') # Process just the first gpo ext.process_group_policy([], gpos[:-1]) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, opts[0], 'Lower priority policy was not set') # Remove policy ext.process_group_policy(del_gpos, []) for guid in guids: gpttmpl = gpofile % (local_path, guid) unstage_file(gpttmpl)
def test_max_update_size(self): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SIGN) self.gensec_client.set_max_update_size(5) self.gensec_client.start_mech_by_name("spnego") self.gensec_server = gensec.Security.start_server( settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx)) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.gensec_server.set_credentials(creds) self.gensec_server.want_feature(gensec.FEATURE_SIGN) self.gensec_server.set_max_update_size(5) self.gensec_server.start_mech_by_name("spnego") client_finished = False server_finished = False server_to_client = b"" """Run the actual call loop""" i = 0 while not client_finished or not server_finished: i += 1 if not client_finished: print("running client gensec_update: %d: %r" % (len(server_to_client), server_to_client)) (client_finished, client_to_server ) = self.gensec_client.update(server_to_client) if not server_finished: print("running server gensec_update: %d: %r" % (len(client_to_server), client_to_server)) (server_finished, server_to_client ) = self.gensec_server.update(client_to_server) """Here we expect a lot more than the typical 1 or 2 roundtrips""" self.assertTrue(i > 10) session_info = self.gensec_server.session_info() test_bytes = b"Hello Server" test_wrapped = self.gensec_client.wrap(test_bytes) test_unwrapped = self.gensec_server.unwrap(test_wrapped) self.assertEqual(test_bytes, test_unwrapped) test_bytes = b"Hello Client" test_wrapped = self.gensec_server.wrap(test_bytes) test_unwrapped = self.gensec_client.unwrap(test_wrapped) self.assertEqual(test_bytes, test_unwrapped) client_session_key = self.gensec_client.session_key() server_session_key = self.gensec_server.session_key() self.assertEqual(client_session_key, server_session_key)
def test_gp_scripts(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_scripts_ext(logger, self.lp, machine_creds, store) ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) reg_key = b'Software\\Policies\\Samba\\Unix Settings' sections = { b'%s\\Daily Scripts' % reg_key: '.cron.daily', b'%s\\Monthly Scripts' % reg_key: '.cron.monthly', b'%s\\Weekly Scripts' % reg_key: '.cron.weekly', b'%s\\Hourly Scripts' % reg_key: '.cron.hourly' } for keyname in sections.keys(): # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = keyname e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory(sections[keyname]) as dname: ext.process_group_policy([], gpos, dname) scripts = os.listdir(dname) self.assertEquals( len(scripts), 1, 'The %s script was not created' % keyname.decode()) out, _ = Popen([os.path.join(dname, scripts[0])], stdout=PIPE).communicate() self.assertIn(b'hello world', out, '%s script execution failed' % keyname.decode()) # Unstage the Registry.pol file unstage_file(reg_pol)
def _load_samba_environment(): """Load the samba configuration vars from smb.conf and the sam.db.""" params = samba.param.LoadParm() params.load_default() netbiosname = params.get("netbios name") hostname = netbiosname.lower() dnsdomain = params.get("realm") dnsdomain = dnsdomain.lower() creds = Credentials() creds.guess(params) creds.set_machine_account(params) samdb_url = params.get('dcerpc_mapiproxy:samdb_url') if samdb_url is None: samdb_url = params.samdb_url() samdb_ldb = SamDBWrapper(url=samdb_url, session_info=system_session(), credentials=creds, lp=params) domaindn = samdb_ldb.domain_dn() rootdn = domaindn configdn = "CN=Configuration," + rootdn # FIXME: Hardcoded strings, those should be queried to LDB, just like # openchange.provision.guess_names_from_smbconf does. firstorg = FIRST_ORGANIZATION firstou = FIRST_ORGANIZATION_UNIT username_mail = False if params.get("auth:usernames are emails") == 'yes': username_mail = True sam_environ = {"samdb_ldb": samdb_ldb, "private_dir": params.get("private dir"), "domaindn": domaindn, "oc_user_basedn": "CN=%s,CN=%s,CN=%s,%s" \ % (firstou, firstorg, netbiosname, domaindn), "firstorgdn": ("CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)), "legacyserverdn": ("/o=%s/ou=%s/cn=Configuration/cn=Servers" "/cn=%s" % (firstorg, firstou, netbiosname)), "hostname": hostname, "dnsdomain": dnsdomain, 'username_mail': username_mail, } # OpenChange dispatcher DB names return sam_environ
def test_pac_groups(self): if creds.get_kerberos_state() == DONT_USE_KERBEROS: self.skipTest("Kerberos disabled, skipping PAC test") settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials(creds) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail( msg="calculated groups don't match against user PAC tokenGroups" )
def test_max_update_size(self): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SIGN) self.gensec_client.set_max_update_size(5) self.gensec_client.start_mech_by_name("spnego") self.gensec_server = gensec.Security.start_server( settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx) ) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.gensec_server.set_credentials(creds) self.gensec_server.want_feature(gensec.FEATURE_SIGN) self.gensec_server.set_max_update_size(5) self.gensec_server.start_mech_by_name("spnego") client_finished = False server_finished = False server_to_client = "" """Run the actual call loop""" i = 0 while not client_finished or not server_finished: i += 1 if not client_finished: print("running client gensec_update: %d: %r" % (len(server_to_client), server_to_client)) (client_finished, client_to_server) = self.gensec_client.update(server_to_client) if not server_finished: print("running server gensec_update: %d: %r" % (len(client_to_server), client_to_server)) (server_finished, server_to_client) = self.gensec_server.update(client_to_server) """Here we expect a lot more than the typical 1 or 2 roundtrips""" self.assertTrue(i > 10) session_info = self.gensec_server.session_info() test_string = "Hello Server" test_wrapped = self.gensec_client.wrap(test_string) test_unwrapped = self.gensec_server.unwrap(test_wrapped) self.assertEqual(test_string, test_unwrapped) test_string = "Hello Client" test_wrapped = self.gensec_server.wrap(test_string) test_unwrapped = self.gensec_client.unwrap(test_wrapped) self.assertEqual(test_string, test_unwrapped) client_session_key = self.gensec_client.session_key() server_session_key = self.gensec_server.session_key() self.assertEqual(client_session_key, server_session_key)
def test_lsa_LookupNames4_multiple_conns(self): """ Test by going back and forward between real DB lookups name->sid->name to ensure the sam.ldb handle is fine once shared """ machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c_normal = lsa.lsarpc( "ncacn_np:%s[seal]" % self.server, self.lp, machine_creds) username, domain = c_normal.GetUserName(None, None, None) c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) sids = lsa.TransSidArray3() names = [username] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 (domains, sids, count) = c.LookupNames4(names, sids, level, count, lookup_options, client_revision) c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) sids = lsa.TransSidArray3() names = [username] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 (domains, sids, count) = c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
def test_lsa_LookupSids3_multiple_conns(self): machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) sids = lsa.SidArray() sid = lsa.SidPtr() # Need a set x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray2() level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 # We want to run LookupSids3, and then again on a new # connection to show that we don't have an issue with the DB # being tied to the wrong connection. (domains, names, count) = c.LookupSids3(sids, names, level, count, lookup_options, client_revision) self.assertEqual(count, 1) self.assertEqual(names.count, 1) self.assertEqual(names.names[0].name.string, "ANONYMOUS LOGON") c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) (domains, names, count) = c.LookupSids3(sids, names, level, count, lookup_options, client_revision) self.assertEqual(count, 1) self.assertEqual(names.count, 1) self.assertEqual(names.names[0].name.string, "ANONYMOUS LOGON")
def test_gp_sudoers(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_sudoers_ext(logger, self.lp, machine_creds, store) ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) sudoers = os.listdir(dname) self.assertEquals(len(sudoers), 1, 'The sudoer file was not created') self.assertIn(e.data, open(os.path.join(dname, sudoers[0]), 'r').read(), 'The sudoers entry was not applied') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEquals(len(os.listdir(dname)), 0, 'Unapply failed to cleanup scripts') # Unstage the Registry.pol file unstage_file(reg_pol)
def test_pac_groups(self): if creds.get_kerberos_state() == DONT_USE_KERBEROS: self.skipTest("Kerberos disabled, skipping PAC test") settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = lp.get("netbios name") gensec_client = gensec.Security.start_client(settings) gensec_client.set_credentials(creds) gensec_client.want_feature(gensec.FEATURE_SEAL) gensec_client.start_mech_by_sasl_name("GSSAPI") auth_context = AuthContext(lp_ctx=lp, ldb=self.ldb, methods=[]) gensec_server = gensec.Security.start_server(settings, auth_context) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_machine_account(lp) gensec_server.set_credentials(machine_creds) gensec_server.want_feature(gensec.FEATURE_SEAL) gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" (client_finished, client_to_server) = gensec_client.update(server_to_client) if not server_finished: print "running server gensec_update" (server_finished, server_to_client) = gensec_server.update(client_to_server) session = gensec_server.session_info() token = session.security_token pac_sids = [] for s in token.sids: pac_sids.append(str(s)) sidset1 = set(pac_sids) sidset2 = set(self.user_sids) if len(sidset1.difference(sidset2)): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail(msg="calculated groups don't match against user PAC tokenGroups")
def test_update(self): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SEAL) self.gensec_client.start_mech_by_sasl_name("GSSAPI") self.gensec_server = gensec.Security.start_server( settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx) ) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.gensec_server.set_credentials(creds) self.gensec_server.want_feature(gensec.FEATURE_SEAL) self.gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = "" """Run the actual call loop""" while not client_finished and not server_finished: if not client_finished: print("running client gensec_update") (client_finished, client_to_server) = self.gensec_client.update(server_to_client) if not server_finished: print("running server gensec_update") (server_finished, server_to_client) = self.gensec_server.update(client_to_server) session_info = self.gensec_server.session_info() test_string = "Hello Server" test_wrapped = self.gensec_client.wrap(test_string) test_unwrapped = self.gensec_server.unwrap(test_wrapped) self.assertEqual(test_string, test_unwrapped) test_string = "Hello Client" test_wrapped = self.gensec_server.wrap(test_string) test_unwrapped = self.gensec_client.unwrap(test_wrapped) self.assertEqual(test_string, test_unwrapped) client_session_key = self.gensec_client.session_key() server_session_key = self.gensec_server.session_key() self.assertEqual(client_session_key, server_session_key)
def test_update(self): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SEAL) self.gensec_client.start_mech_by_sasl_name("GSSAPI") self.gensec_server = gensec.Security.start_server( settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx)) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.gensec_server.set_credentials(creds) self.gensec_server.want_feature(gensec.FEATURE_SEAL) self.gensec_server.start_mech_by_sasl_name("GSSAPI") client_finished = False server_finished = False server_to_client = b"" """Run the actual call loop""" while not client_finished and not server_finished: if not client_finished: print("running client gensec_update") (client_finished, client_to_server ) = self.gensec_client.update(server_to_client) if not server_finished: print("running server gensec_update") (server_finished, server_to_client ) = self.gensec_server.update(client_to_server) session_info = self.gensec_server.session_info() test_bytes = b"Hello Server" test_wrapped = self.gensec_client.wrap(test_bytes) test_unwrapped = self.gensec_server.unwrap(test_wrapped) self.assertEqual(test_bytes, test_unwrapped) test_bytes = b"Hello Client" test_wrapped = self.gensec_server.wrap(test_bytes) test_unwrapped = self.gensec_client.unwrap(test_wrapped) self.assertEqual(test_bytes, test_unwrapped) client_session_key = self.gensec_client.session_key() server_session_key = self.gensec_server.session_key() self.assertEqual(client_session_key, server_session_key)
def test_lsa_LookupSids3_multiple(self): machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) sids = lsa.SidArray() sid = lsa.SidPtr() # Need a set x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray2() level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 # We want to run LookupSids3 multiple times on the same # connection as we have code to re-use the sam.ldb and we need # to check things work for the second request. (domains, names, count) = c.LookupSids3(sids, names, level, count, lookup_options, client_revision) self.assertEqual(count, 1) self.assertEqual(names.count, 1) self.assertEqual(names.names[0].name.string, "ANONYMOUS LOGON") (domains2, names2, count2) = c.LookupSids3(sids, names, level, count, lookup_options, client_revision) self.assertEqual(count2, 1) self.assertEqual(names2.count, 1) self.assertEqual(names2.names[0].name.string, "ANONYMOUS LOGON") # Just looking for any exceptions in the last couple of loops c.LookupSids3(sids, names, level, count, lookup_options, client_revision) c.LookupSids3(sids, names, level, count, lookup_options, client_revision)
class CredentialsOptions(optparse.OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser, special_name=None): self.special_name = special_name if special_name is not None: self.section = "Credentials Options (%s)" % special_name else: self.section = "Credentials Options" self.ask_for_password = True self.ipaddress = None self.machine_pass = False optparse.OptionGroup.__init__(self, parser, self.section) self._add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") self._add_option("--password", metavar="PASSWORD", action="callback", help="Password", type=str, callback=self._set_password) self._add_option("-U", "--username", metavar="USERNAME", action="callback", type=str, help="Username", callback=self._parse_username) self._add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) self._add_option("-N", "--no-pass", action="callback", help="Don't ask for a password", callback=self._set_no_password) self._add_option("-k", "--kerberos", metavar="KERBEROS", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos) self._add_option("", "--ipaddress", metavar="IPADDRESS", action="callback", type=str, help="IP address of server", callback=self._set_ipaddress) self._add_option("-P", "--machine-pass", action="callback", help="Use stored machine account password", callback=self._set_machine_pass) self._add_option("--krb5-ccache", metavar="KRB5CCNAME", action="callback", type=str, help="Kerberos Credentials cache", callback=self._set_krb5_ccache) self.creds = Credentials() def _add_option(self, *args1, **kwargs): if self.special_name is None: return self.add_option(*args1, **kwargs) args2 = () for a in args1: if not a.startswith("--"): continue args2 += (a.replace("--", "--%s-" % self.special_name),) self.add_option(*args2, **kwargs) def _parse_username(self, option, opt_str, arg, parser): self.creds.parse_string(arg) self.machine_pass = False def _parse_workgroup(self, option, opt_str, arg, parser): self.creds.set_domain(arg) def _set_password(self, option, opt_str, arg, parser): self.creds.set_password(arg) self.ask_for_password = False self.machine_pass = False def _set_no_password(self, option, opt_str, arg, parser): self.ask_for_password = False def _set_machine_pass(self, option, opt_str, arg, parser): self.machine_pass = True def _set_ipaddress(self, option, opt_str, arg, parser): self.ipaddress = arg def _set_kerberos(self, option, opt_str, arg, parser): self.creds.set_kerberos_state(parse_kerberos_arg(arg, opt_str)) def _set_simple_bind_dn(self, option, opt_str, arg, parser): self.creds.set_bind_dn(arg) def _set_krb5_ccache(self, option, opt_str, arg, parser): self.creds.set_named_ccache(arg) def get_credentials(self, lp, fallback_machine=False): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :return: Credentials object """ self.creds.guess(lp) if self.machine_pass: self.creds.set_machine_account(lp) elif self.ask_for_password: self.creds.set_cmdline_callbacks() # possibly fallback to using the machine account, if we have # access to the secrets db if fallback_machine and not self.creds.authentication_requested(): try: self.creds.set_machine_account(lp) except Exception: pass return self.creds
def _load_samba_environment(): """Load the samba configuration vars from smb.conf and the sam.db.""" params = samba.param.LoadParm() params.load_default() netbiosname = params.get("netbios name") hostname = netbiosname.lower() dnsdomain = params.get("realm") dnsdomain = dnsdomain.lower() creds = Credentials() creds.guess(params) creds.set_machine_account(params) samdb_url = params.get('dcerpc_mapiproxy:samdb_url') if samdb_url is None: samdb_url = params.samdb_url() samdb_ldb = SamDBWrapper(url=samdb_url, session_info=system_session(), credentials=creds, lp=params) domaindn = samdb_ldb.domain_dn() rootdn = domaindn configdn = "CN=Configuration," + rootdn firstorg = None firstorg_basedn = 'CN=Microsoft Exchange,CN=Services,' + configdn res = samdb_ldb.search( base=firstorg_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchOrganizationContainer)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange organization found') firstorg = res[0]['cn'][0] if not firstorg: raise Exception( "Cannot find first exchange organization in samba database") firstou = None firstou_basedn = "CN=Administrative Groups,CN=%s,%s" % (firstorg, firstorg_basedn) res = samdb_ldb.search(base=firstou_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchAdminGroup)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange administration group found') firstou = res[0]['cn'][0] if not firstou: raise Exception( "Cannot find exchange first organization unit in samba database") username_mail = False if params.get("auth:usernames are emails") == 'yes': username_mail = True sam_environ = {"samdb_ldb": samdb_ldb, "private_dir": params.get("private dir"), "domaindn": domaindn, "oc_user_basedn": "CN=%s,CN=%s,CN=%s,%s" \ % (firstou, firstorg, netbiosname, domaindn), "firstorgdn": ("CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)), "legacyserverdn": ("/o=%s/ou=%s/cn=Configuration/cn=Servers" "/cn=%s" % (firstorg, firstou, netbiosname)), "hostname": hostname, "dnsdomain": dnsdomain, 'username_mail': username_mail, } # OpenChange dispatcher DB names return sam_environ
def test_lsa_LookupNames4_LookupSids3_multiple(self): """ Test by going back and forward between real DB lookups name->sid->name to ensure the sam.ldb handle is fine once shared """ machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() c_normal = lsa.lsarpc( "ncacn_np:%s[seal]" % self.server, self.lp, machine_creds) username, domain = c_normal.GetUserName(None, None, None) c = lsa.lsarpc( "ncacn_ip_tcp:%s[schannel,seal]" % self.server, self.lp, machine_creds) sids = lsa.TransSidArray3() names = [username] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 (domains, sids, count) = c.LookupNames4(names, sids, level, count, lookup_options, client_revision) # Another lookup on the same connection, will re-used the # server-side implicit state handle on the connection (domains, sids, count) = c.LookupNames4(names, sids, level, count, lookup_options, client_revision) self.assertEqual(count, 1) self.assertEqual(sids.count, 1) # Now look the SIDs back up names = lsa.TransNameArray2() sid = lsa.SidPtr() sid.sid = sids.sids[0].sid lookup_sids = lsa.SidArray() lookup_sids.sids = [sid] lookup_sids.num_sids = 1 level = lsa.LSA_LOOKUP_NAMES_ALL count = 1 lookup_options = 0 client_revision = lsa.LSA_CLIENT_REVISION_2 (domains, names, count) = c.LookupSids3(lookup_sids, names, level, count, lookup_options, client_revision) self.assertEqual(count, 1) self.assertEqual(names.count, 1) self.assertEqual(names.names[0].name.string, username.string) # And once more just to be sure, just checking for a fault sids = lsa.TransSidArray3() names = [username] level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 (domains, sids, count) = c.LookupNames4(names, sids, level, count, lookup_options, client_revision)
class CredentialsOptions(optparse.OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser, special_name=None): self.special_name = special_name if special_name is not None: self.section = "Credentials Options (%s)" % special_name else: self.section = "Credentials Options" self.ask_for_password = True self.ipaddress = None self.machine_pass = False optparse.OptionGroup.__init__(self, parser, self.section) self._add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") self._add_option("--password", metavar="PASSWORD", action="callback", help="Password", type=str, callback=self._set_password) self._add_option("-U", "--username", metavar="USERNAME", action="callback", type=str, help="Username", callback=self._parse_username) self._add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) self._add_option("-N", "--no-pass", action="callback", help="Don't ask for a password", callback=self._set_no_password) self._add_option("-k", "--kerberos", metavar="KERBEROS", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos) self._add_option("", "--ipaddress", metavar="IPADDRESS", action="callback", type=str, help="IP address of server", callback=self._set_ipaddress) self._add_option("-P", "--machine-pass", action="callback", help="Use stored machine account password", callback=self._set_machine_pass) self.creds = Credentials() def _add_option(self, *args1, **kwargs): if self.special_name is None: return self.add_option(*args1, **kwargs) args2 = () for a in args1: if not a.startswith("--"): continue args2 += (a.replace("--", "--%s-" % self.special_name), ) self.add_option(*args2, **kwargs) def _parse_username(self, option, opt_str, arg, parser): self.creds.parse_string(arg) self.machine_pass = False def _parse_workgroup(self, option, opt_str, arg, parser): self.creds.set_domain(arg) def _set_password(self, option, opt_str, arg, parser): self.creds.set_password(arg) self.ask_for_password = False self.machine_pass = False def _set_no_password(self, option, opt_str, arg, parser): self.ask_for_password = False def _set_machine_pass(self, option, opt_str, arg, parser): self.machine_pass = True def _set_ipaddress(self, option, opt_str, arg, parser): self.ipaddress = arg def _set_kerberos(self, option, opt_str, arg, parser): self.creds.set_kerberos_state(parse_kerberos_arg(arg, opt_str)) def _set_simple_bind_dn(self, option, opt_str, arg, parser): self.creds.set_bind_dn(arg) def get_credentials(self, lp, fallback_machine=False): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :return: Credentials object """ self.creds.guess(lp) if self.machine_pass: self.creds.set_machine_account(lp) elif self.ask_for_password: self.creds.set_cmdline_callbacks() # possibly fallback to using the machine account, if we have # access to the secrets db if fallback_machine and not self.creds.authentication_requested(): try: self.creds.set_machine_account(lp) except Exception: pass return self.creds
def test_rsop(self): logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') local_path = self.lp.cache_path('gpo_cache') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) gp_extensions = [] gp_extensions.append(gp_krb_ext(logger, self.lp, machine_creds, store)) gp_extensions.append( gp_scripts_ext(logger, self.lp, machine_creds, store)) # Create registry stage data reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL') reg_stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' reg_stage.num_entries = 1 reg_stage.entries = [e] # Create krb stage date gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF') krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n' for g in [g for g in gpos if g.file_sys_path]: ret = stage_file(gpofile % g.name, krb_stage) self.assertTrue( ret, 'Could not create the target %s' % (gpofile % g.name)) ret = stage_file(reg_pol % g.name, ndr_pack(reg_stage)) self.assertTrue( ret, 'Could not create the target %s' % (reg_pol % g.name)) for ext in gp_extensions: ret = ext.rsop(g) self.assertEquals( len(ret.keys()), 1, 'A single policy should have been displayed') # Check the Security Extension if type(ext) == gp_krb_ext: self.assertIn('Kerberos Policy', ret.keys(), 'Kerberos Policy not found') self.assertIn('MaxTicketAge', ret['Kerberos Policy'], 'MaxTicketAge setting not found') self.assertEquals(ret['Kerberos Policy']['MaxTicketAge'], '99', 'MaxTicketAge was not set to 99') # Check the Scripts Extension elif type(ext) == gp_scripts_ext: self.assertIn('Daily Scripts', ret.keys(), 'Daily Scripts not found') self.assertIn('echo hello world', ret['Daily Scripts'], 'Daily script was not created') unstage_file(gpofile % g.name) unstage_file(reg_pol % g.name)
def test_gp_motd(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_msgs_ext(logger, self.lp, machine_creds, store) ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e1 = preg.entry() e1.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e1.valuename = b'motd' e1.type = 1 e1.data = b'Have a lot of fun!' stage.num_entries = 2 e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e2.valuename = b'issue' e2.type = 1 e2.data = b'Welcome to \\s \\r \\l' stage.entries = [e1, e2] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) motd_file = os.path.join(dname, 'motd') self.assertTrue(os.path.exists(motd_file), 'Message of the day file not created') data = open(motd_file, 'r').read() self.assertEquals(data, e1.data, 'Message of the day not applied') issue_file = os.path.join(dname, 'issue') self.assertTrue(os.path.exists(issue_file), 'Login Prompt Message file not created') data = open(issue_file, 'r').read() self.assertEquals(data, e2.data, 'Login Prompt Message not applied') # Unapply policy, and ensure the test files are removed gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) data = open(motd_file, 'r').read() self.assertFalse(data, 'Message of the day file not removed') data = open(issue_file, 'r').read() self.assertFalse(data, 'Login Prompt Message file not removed') # Unstage the Registry.pol file unstage_file(reg_pol)
def _load_samba_environment(): """Load the samba configuration vars from smb.conf and the sam.db.""" params = samba.param.LoadParm() params.load_default() netbiosname = params.get("netbios name") hostname = netbiosname.lower() dnsdomain = params.get("realm") dnsdomain = dnsdomain.lower() creds = Credentials() creds.guess(params) creds.set_machine_account(params) samdb_url = params.get('dcerpc_mapiproxy:samdb_url') if samdb_url is None: samdb_url = params.samdb_url() samdb_ldb = SamDBWrapper(url=samdb_url, session_info=system_session(), credentials=creds, lp=params) domaindn = samdb_ldb.domain_dn() rootdn = domaindn configdn = "CN=Configuration," + rootdn firstorg = None firstorg_basedn = 'CN=Microsoft Exchange,CN=Services,' + configdn res = samdb_ldb.search(base=firstorg_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchOrganizationContainer)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange organization found') firstorg = res[0]['cn'][0] if not firstorg: raise Exception("Cannot find first exchange organization in samba database") firstou = None firstou_basedn = "CN=Administrative Groups,CN=%s,%s" %(firstorg, firstorg_basedn) res = samdb_ldb.search(base=firstou_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchAdminGroup)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange administration group found') firstou = res[0]['cn'][0] if not firstou: raise Exception("Cannot find exchange first organization unit in samba database") username_mail = False if params.get("auth:usernames are emails") == 'yes': username_mail = True sam_environ = {"samdb_ldb": samdb_ldb, "private_dir": params.get("private dir"), "domaindn": domaindn, "oc_user_basedn": "CN=%s,CN=%s,CN=%s,%s" \ % (firstou, firstorg, netbiosname, domaindn), "firstorgdn": ("CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)), "legacyserverdn": ("/o=%s/ou=%s/cn=Configuration/cn=Servers" "/cn=%s" % (firstorg, firstou, netbiosname)), "hostname": hostname, "dnsdomain": dnsdomain, 'username_mail': username_mail, } # OpenChange dispatcher DB names return sam_environ
def test_gp_unapply(self): logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) gp_extensions = [] gp_extensions.append(gp_krb_ext) gp_extensions.append(gp_scripts_ext) gp_extensions.append(gp_sudoers_ext) # Create registry stage data reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL') reg_stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e2.valuename = b'Software\\Policies\\Samba\\Unix Settings' e2.type = 1 e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' reg_stage.num_entries = 2 reg_stage.entries = [e, e2] # Create krb stage date gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF') krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n' ret = stage_file(gpofile % guid, krb_stage) self.assertTrue(ret, 'Could not create the target %s' % (gpofile % guid)) ret = stage_file(reg_pol % guid, ndr_pack(reg_stage)) self.assertTrue(ret, 'Could not create the target %s' % (reg_pol % guid)) # Process all gpos, with temp output directory remove = [] with TemporaryDirectory() as dname: for ext in gp_extensions: ext = ext(logger, self.lp, machine_creds, store) if type(ext) == gp_krb_ext: ext.process_group_policy([], gpos) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, 99, 'Kerberos policy was not set') elif type(ext) in [gp_scripts_ext, gp_sudoers_ext]: ext.process_group_policy([], gpos, dname) gp_db = store.get_gplog(machine_creds.get_username()) applied_settings = gp_db.get_applied_settings([guid]) for _, fname in applied_settings[-1][-1][str(ext)].items(): self.assertIn(dname, fname, 'Test file not created in tmp dir') self.assertTrue(os.path.exists(fname), 'Test file not created') remove.append(fname) # Unapply policy, and ensure policies are removed gpupdate_unapply(self.lp) for fname in remove: self.assertFalse(os.path.exists(fname), 'Unapply did not remove test file') ret = store.get_int('kdc:user_ticket_lifetime') self.assertNotEqual(ret, 99, 'Kerberos policy was not unapplied') unstage_file(gpofile % guid) unstage_file(reg_pol % guid)
def test_smb_conf_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) entries = [] e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\template homedir' e.type = 1 e.data = '/home/samba/%D/%U' e.valuename = 'template homedir' entries.append(e) e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies' e.type = 4 e.data = 1 e.valuename = 'apply group policies' entries.append(e) e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\ldap timeout' e.type = 4 e.data = 9999 e.valuename = 'ldap timeout' entries.append(e) stage = preg.file() stage.num_entries = len(entries) stage.entries = entries ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Failed to create the Registry.pol file') with NamedTemporaryFile(suffix='_smb.conf') as f: copyfile(self.lp.configfile, f.name) lp = LoadParm(f.name) # Initialize the group policy extension ext = gp_smb_conf_ext(logger, lp, machine_creds, store) ext.process_group_policy([], gpos) lp = LoadParm(f.name) template_homedir = lp.get('template homedir') self.assertEquals(template_homedir, '/home/samba/%D/%U', 'template homedir was not applied') apply_group_policies = lp.get('apply group policies') self.assertTrue(apply_group_policies, 'apply group policies was not applied') ldap_timeout = lp.get('ldap timeout') self.assertEquals(ldap_timeout, 9999, 'ldap timeout was not applied') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) lp = LoadParm(f.name) template_homedir = lp.get('template homedir') self.assertEquals(template_homedir, self.lp.get('template homedir'), 'template homedir was not unapplied') apply_group_policies = lp.get('apply group policies') self.assertEquals(apply_group_policies, self.lp.get('apply group policies'), 'apply group policies was not unapplied') ldap_timeout = lp.get('ldap timeout') self.assertEquals(ldap_timeout, self.lp.get('ldap timeout'), 'ldap timeout was not unapplied') # Unstage the Registry.pol file unstage_file(reg_pol)
def test_rsop(self): logger = logging.getLogger('gpo_tests') cache_dir = self.lp.get('cache directory') local_path = self.lp.cache_path('gpo_cache') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) gp_extensions = [] gp_extensions.append(gp_krb_ext) gp_extensions.append(gp_scripts_ext) gp_extensions.append(gp_sudoers_ext) gp_extensions.append(gp_smb_conf_ext) gp_extensions.append(gp_msgs_ext) # Create registry stage data reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL') reg_stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e2.valuename = b'Software\\Policies\\Samba\\Unix Settings' e2.type = 1 e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' e3 = preg.entry() e3.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies' e3.type = 4 e3.data = 1 e3.valuename = 'apply group policies' e4 = preg.entry() e4.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e4.valuename = b'issue' e4.type = 1 e4.data = b'Welcome to \\s \\r \\l' reg_stage.num_entries = 4 reg_stage.entries = [e, e2, e3, e4] # Create krb stage date gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF') krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n' for g in [g for g in gpos if g.file_sys_path]: ret = stage_file(gpofile % g.name, krb_stage) self.assertTrue( ret, 'Could not create the target %s' % (gpofile % g.name)) ret = stage_file(reg_pol % g.name, ndr_pack(reg_stage)) self.assertTrue( ret, 'Could not create the target %s' % (reg_pol % g.name)) for ext in gp_extensions: ext = ext(logger, self.lp, machine_creds, store) ret = ext.rsop(g) self.assertEquals( len(ret.keys()), 1, 'A single policy should have been displayed') # Check the Security Extension if type(ext) == gp_krb_ext: self.assertIn('Kerberos Policy', ret.keys(), 'Kerberos Policy not found') self.assertIn('MaxTicketAge', ret['Kerberos Policy'], 'MaxTicketAge setting not found') self.assertEquals(ret['Kerberos Policy']['MaxTicketAge'], '99', 'MaxTicketAge was not set to 99') # Check the Scripts Extension elif type(ext) == gp_scripts_ext: self.assertIn('Daily Scripts', ret.keys(), 'Daily Scripts not found') self.assertIn('echo hello world', ret['Daily Scripts'], 'Daily script was not created') # Check the Sudoers Extension elif type(ext) == gp_sudoers_ext: self.assertIn('Sudo Rights', ret.keys(), 'Sudoers not found') self.assertIn('fakeu ALL=(ALL) NOPASSWD: ALL', ret['Sudo Rights'], 'Sudoers policy not created') # Check the smb.conf Extension elif type(ext) == gp_smb_conf_ext: self.assertIn('smb.conf', ret.keys(), 'apply group policies was not applied') self.assertIn(e3.valuename, ret['smb.conf'], 'apply group policies was not applied') self.assertEquals(ret['smb.conf'][e3.valuename], e3.data, 'apply group policies was not set') # Check the Messages Extension elif type(ext) == gp_msgs_ext: self.assertIn('/etc/issue', ret, 'Login Prompt Message not applied') self.assertEquals(ret['/etc/issue'], e4.data, 'Login Prompt Message not set') unstage_file(gpofile % g.name) unstage_file(reg_pol % g.name) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEquals(ret, 0, 'gpupdate --rsop failed!')
class CredentialsOptions(optparse.OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser, special_name=None): self.special_name = special_name if special_name is not None: self.section = "Credentials Options (%s)" % special_name else: self.section = "Credentials Options" self.ask_for_password = True self.ipaddress = None self.machine_pass = False optparse.OptionGroup.__init__(self, parser, self.section) self._add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") self._add_option("--password", metavar="PASSWORD", action="callback", help="Password", type=str, callback=self._set_password) self._add_option("-U", "--username", metavar="USERNAME", action="callback", type=str, help="Username", callback=self._parse_username) self._add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) self._add_option("-N", "--no-pass", action="callback", help="Don't ask for a password", callback=self._set_no_password) self._add_option("-k", "--kerberos", metavar="KERBEROS", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos) self._add_option("", "--ipaddress", metavar="IPADDRESS", action="callback", type=str, help="IP address of server", callback=self._set_ipaddress) self._add_option("-P", "--machine-pass", action="callback", help="Use stored machine account password", callback=self._set_machine_pass) self._add_option("--krb5-ccache", metavar="KRB5CCNAME", action="callback", type=str, help="Kerberos Credentials cache", callback=self._set_krb5_ccache) self.creds = Credentials() def _ensure_secure_proctitle(self, opt_str, secret_data, data_type="password"): """ Make sure no sensitive data (e.g. password) resides in proctitle. """ import re try: import setproctitle except ModuleNotFoundError: msg = ("WARNING: Using %s on command line is insecure. " "Please install the setproctitle python module.\n" % data_type) sys.stderr.write(msg) sys.stderr.flush() return False # Regex to search and replace secret data + option with. # .*[ ]+ -> Before the option must be one or more spaces. # [= ] -> The option and the secret data might be separated by space # or equal sign. # [ ]*.* -> After the secret data might be one, many or no space. pass_opt_re_str = "(.*[ ]+)(%s[= ]%s)([ ]*.*)" % (opt_str, secret_data) pass_opt_re = re.compile(pass_opt_re_str) # Get current proctitle. cur_proctitle = setproctitle.getproctitle() # Make sure we build the correct regex. if not pass_opt_re.match(cur_proctitle): msg = ("Unable to hide %s in proctitle. This is most likely " "a bug!\n" % data_type) sys.stderr.write(msg) sys.stderr.flush() return False # String to replace secret data with. secret_data_replacer = "xxx" # Build string to replace secret data and option with. And as we dont # want to change anything else than the secret data within the proctitle # we have to check if the option was passed with space or equal sign as # separator. opt_pass_with_eq = "%s=%s" % (opt_str, secret_data) opt_pass_part = re.sub(pass_opt_re_str, r'\2', cur_proctitle) if opt_pass_part == opt_pass_with_eq: replace_str = "%s=%s" % (opt_str, secret_data_replacer) else: replace_str = "%s %s" % (opt_str, secret_data_replacer) # Build new proctitle: new_proctitle = re.sub(pass_opt_re_str, r'\1' + replace_str + r'\3', cur_proctitle) # Set new proctitle. setproctitle.setproctitle(new_proctitle) def _add_option(self, *args1, **kwargs): if self.special_name is None: return self.add_option(*args1, **kwargs) args2 = () for a in args1: if not a.startswith("--"): continue args2 += (a.replace("--", "--%s-" % self.special_name),) self.add_option(*args2, **kwargs) def _parse_username(self, option, opt_str, arg, parser): self.creds.parse_string(arg) self.machine_pass = False def _parse_workgroup(self, option, opt_str, arg, parser): self.creds.set_domain(arg) def _set_password(self, option, opt_str, arg, parser): self._ensure_secure_proctitle(opt_str, arg, "password") self.creds.set_password(arg) self.ask_for_password = False self.machine_pass = False def _set_no_password(self, option, opt_str, arg, parser): self.ask_for_password = False def _set_machine_pass(self, option, opt_str, arg, parser): self.machine_pass = True def _set_ipaddress(self, option, opt_str, arg, parser): self.ipaddress = arg def _set_kerberos(self, option, opt_str, arg, parser): self.creds.set_kerberos_state(parse_kerberos_arg(arg, opt_str)) def _set_simple_bind_dn(self, option, opt_str, arg, parser): self.creds.set_bind_dn(arg) def _set_krb5_ccache(self, option, opt_str, arg, parser): self.creds.set_named_ccache(arg) def get_credentials(self, lp, fallback_machine=False): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :return: Credentials object """ self.creds.guess(lp) if self.machine_pass: self.creds.set_machine_account(lp) elif self.ask_for_password: self.creds.set_cmdline_callbacks() # possibly fallback to using the machine account, if we have # access to the secrets db if fallback_machine and not self.creds.authentication_requested(): try: self.creds.set_machine_account(lp) except Exception: pass return self.creds
class CredentialsOptions(optparse.OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser): self.no_pass = True self.ipaddress = None optparse.OptionGroup.__init__(self, parser, "Credentials Options") self.add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") self.add_option("--password", metavar="PASSWORD", action="callback", help="Password", type=str, callback=self._set_password) self.add_option("-U", "--username", metavar="USERNAME", action="callback", type=str, help="Username", callback=self._parse_username) self.add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) self.add_option("-N", "--no-pass", action="store_true", help="Don't ask for a password") self.add_option("-k", "--kerberos", metavar="KERBEROS", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos) self.add_option("", "--ipaddress", metavar="IPADDRESS", action="callback", type=str, help="IP address of server", callback=self._set_ipaddress) self.creds = Credentials() def _parse_username(self, option, opt_str, arg, parser): self.creds.parse_string(arg) def _parse_workgroup(self, option, opt_str, arg, parser): self.creds.set_domain(arg) def _set_password(self, option, opt_str, arg, parser): self.creds.set_password(arg) self.no_pass = False def _set_ipaddress(self, option, opt_str, arg, parser): self.ipaddress = arg def _set_kerberos(self, option, opt_str, arg, parser): self.creds.set_kerberos_state(parse_kerberos_arg(arg, opt_str)) def _set_simple_bind_dn(self, option, opt_str, arg, parser): self.creds.set_bind_dn(arg) def get_credentials(self, lp, fallback_machine=False): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :return: Credentials object """ self.creds.guess(lp) if self.no_pass: self.creds.set_cmdline_callbacks() # possibly fallback to using the machine account, if we have # access to the secrets db if fallback_machine and not self.creds.authentication_requested(): try: self.creds.set_machine_account(lp) except Exception: pass return self.creds
def _load_samba_environment(retries): """Load the samba configuration vars from smb.conf and the sam.db.""" params = samba.param.LoadParm() params.load_default() netbiosname = params.get("netbios name") hostname = netbiosname.lower() dnsdomain = params.get("realm") dnsdomain = dnsdomain.lower() creds = Credentials() creds.guess(params) creds.set_machine_account(params) samdb_url = params.get('dcerpc_mapiproxy:samdb_url') if samdb_url is None: samdb_url = params.samdb_url() samdb_ldb = None backoff = 0.2 next_retry = 0 while samdb_ldb is None: try: samdb_ldb = SamDBWrapper(url=samdb_url, session_info=system_session(), credentials=creds, lp=params) except ldb.LdbError as ex: number, desc = ex if number == ldb.ERR_OPERATIONS_ERROR: # this is a cannot connect error if retries != 0: next_retry += 1 if next_retry > retries: logger.error( "Maximum samba connection retries reached (%i)" % retries) raise ex logger.warn( "Cannot connect to samba server. Backing off for %.2f seconds" % backoff) time.sleep(backoff) backoff *= 2 if backoff > 60: backoff = 60 else: raise ex domaindn = samdb_ldb.domain_dn() rootdn = domaindn configdn = "CN=Configuration," + rootdn firstorg = None firstorg_basedn = 'CN=Microsoft Exchange,CN=Services,' + configdn res = samdb_ldb.search( base=firstorg_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchOrganizationContainer)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange organization found') firstorg = res[0]['cn'][0] if not firstorg: raise Exception( "Cannot find first exchange organization in samba database") firstou = None firstou_basedn = "CN=Administrative Groups,CN=%s,%s" % (firstorg, firstorg_basedn) res = samdb_ldb.search(base=firstou_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchAdminGroup)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange administration group found') firstou = res[0]['cn'][0] if not firstou: raise Exception( "Cannot find exchange first organization unit in samba database") username_mail = False if params.get("auth:usernames are emails") == 'yes': username_mail = True sam_environ = {"samdb_ldb": samdb_ldb, "private_dir": params.get("private dir"), "domaindn": domaindn, "oc_user_basedn": "CN=%s,CN=%s,CN=%s,%s" \ % (firstou, firstorg, netbiosname, domaindn), "firstorgdn": ("CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)), "legacyserverdn": ("/o=%s/ou=%s/cn=Configuration/cn=Servers" "/cn=%s" % (firstorg, firstou, netbiosname)), "hostname": hostname, "dnsdomain": dnsdomain, 'username_mail': username_mail, } return sam_environ
class CredentialsOptions(optparse.OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser): self.no_pass = True self.ipaddress = None optparse.OptionGroup.__init__(self, parser, "Credentials Options") self.add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") self.add_option("--password", metavar="PASSWORD", action="callback", help="Password", type=str, callback=self._set_password) self.add_option("-U", "--username", metavar="USERNAME", action="callback", type=str, help="Username", callback=self._parse_username) self.add_option("-W", "--workgroup", metavar="WORKGROUP", action="callback", type=str, help="Workgroup", callback=self._parse_workgroup) self.add_option("-N", "--no-pass", action="store_true", help="Don't ask for a password") self.add_option("-k", "--kerberos", metavar="KERBEROS", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos) self.add_option("", "--ipaddress", metavar="IPADDRESS", action="callback", type=str, help="IP address of server", callback=self._set_ipaddress) self.creds = Credentials() def _parse_username(self, option, opt_str, arg, parser): self.creds.parse_string(arg) def _parse_workgroup(self, option, opt_str, arg, parser): self.creds.set_domain(arg) def _set_password(self, option, opt_str, arg, parser): self.creds.set_password(arg) self.no_pass = False def _set_ipaddress(self, option, opt_str, arg, parser): self.ipaddress = arg def _set_kerberos(self, option, opt_str, arg, parser): if arg.lower() in ["yes", 'true', '1']: self.creds.set_kerberos_state(MUST_USE_KERBEROS) elif arg.lower() in ["no", 'false', '0']: self.creds.set_kerberos_state(DONT_USE_KERBEROS) else: raise optparse.BadOptionErr("invalid kerberos option: %s" % arg) def _set_simple_bind_dn(self, option, opt_str, arg, parser): self.creds.set_bind_dn(arg) def get_credentials(self, lp, fallback_machine=False): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :return: Credentials object """ self.creds.guess(lp) if self.no_pass: self.creds.set_cmdline_callbacks() # possibly fallback to using the machine account, if we have # access to the secrets db if fallback_machine and not self.creds.authentication_requested(): try: self.creds.set_machine_account(lp) except Exception: pass return self.creds
def _load_samba_environment(retries): """Load the samba configuration vars from smb.conf and the sam.db.""" params = samba.param.LoadParm() params.load_default() netbiosname = params.get("netbios name") hostname = netbiosname.lower() dnsdomain = params.get("realm") dnsdomain = dnsdomain.lower() creds = Credentials() creds.guess(params) creds.set_machine_account(params) samdb_url = params.get('dcerpc_mapiproxy:samdb_url') if samdb_url is None: samdb_url = params.samdb_url() samdb_ldb = None backoff = 0.2 next_retry = 0 while samdb_ldb is None: try: samdb_ldb = SamDBWrapper(url=samdb_url, session_info=system_session(), credentials=creds, lp=params) except ldb.LdbError as ex: number, desc = ex if number == ldb.ERR_OPERATIONS_ERROR: # this is a cannot connect error if retries != 0: next_retry += 1 if next_retry > retries: logger.error("Maximum samba connection retries reached (%i)" % retries) raise ex logger.warn("Cannot connect to samba server. Backing off for %.2f seconds" % backoff) time.sleep(backoff) backoff *= 2 if backoff > 60: backoff = 60 else: raise ex domaindn = samdb_ldb.domain_dn() rootdn = domaindn configdn = "CN=Configuration," + rootdn firstorg = None firstorg_basedn = 'CN=Microsoft Exchange,CN=Services,' + configdn res = samdb_ldb.search(base=firstorg_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchOrganizationContainer)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange organization found') firstorg = res[0]['cn'][0] if not firstorg: raise Exception("Cannot find first exchange organization in samba database") firstou = None firstou_basedn = "CN=Administrative Groups,CN=%s,%s" %(firstorg, firstorg_basedn) res = samdb_ldb.search(base=firstou_basedn, scope=ldb.SCOPE_ONELEVEL, expression='(objectClass=msExchAdminGroup)', attrs=['cn']) if res: if len(res) > 1: logger.warn('More than one exchange administration group found') firstou = res[0]['cn'][0] if not firstou: raise Exception("Cannot find exchange first organization unit in samba database") username_mail = False if params.get("auth:usernames are emails") == 'yes': username_mail = True sam_environ = {"samdb_ldb": samdb_ldb, "private_dir": params.get("private dir"), "domaindn": domaindn, "oc_user_basedn": "CN=%s,CN=%s,CN=%s,%s" \ % (firstou, firstorg, netbiosname, domaindn), "firstorgdn": ("CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)), "legacyserverdn": ("/o=%s/ou=%s/cn=Configuration/cn=Servers" "/cn=%s" % (firstorg, firstou, netbiosname)), "hostname": hostname, "dnsdomain": dnsdomain, 'username_mail': username_mail, } return sam_environ
def _test_update(self, mech, client_mech=None, client_only_opt=None): """Test GENSEC by doing an exchange with ourselves using GSSAPI against a KDC""" """Start up a client and server GENSEC instance to test things with""" if client_only_opt: orig_client_opt = self.lp_ctx.get(client_only_opt) if not orig_client_opt: orig_client_opt = '' self.lp_ctx.set(client_only_opt, "yes") self.gensec_client = gensec.Security.start_client(self.settings) self.gensec_client.set_credentials(self.get_credentials()) self.gensec_client.want_feature(gensec.FEATURE_SEAL) if client_mech is not None: self.gensec_client.start_mech_by_name(client_mech) else: self.gensec_client.start_mech_by_sasl_name(mech) if client_only_opt: self.lp_ctx.set(client_only_opt, "no") self.gensec_server = gensec.Security.start_server( settings=self.settings, auth_context=auth.AuthContext(lp_ctx=self.lp_ctx)) creds = Credentials() creds.guess(self.lp_ctx) creds.set_machine_account(self.lp_ctx) self.gensec_server.set_credentials(creds) self.gensec_server.want_feature(gensec.FEATURE_SEAL) self.gensec_server.start_mech_by_sasl_name(mech) client_finished = False server_finished = False server_to_client = b"" client_to_server = b"" """Run the actual call loop""" while True: if not client_finished: if client_only_opt: self.lp_ctx.set(client_only_opt, "yes") print("running client gensec_update") try: (client_finished, client_to_server ) = self.gensec_client.update(server_to_client) except samba.NTSTATUSError as nt: raise AssertionError(nt) if client_only_opt: self.lp_ctx.set(client_only_opt, "no") if not server_finished: print("running server gensec_update") try: (server_finished, server_to_client ) = self.gensec_server.update(client_to_server) except samba.NTSTATUSError as nt: raise AssertionError(nt) if client_finished and server_finished: break if client_only_opt: self.lp_ctx.set(client_only_opt, orig_client_opt) self.assertTrue(server_finished) self.assertTrue(client_finished) session_info = self.gensec_server.session_info() test_bytes = b"Hello Server" try: test_wrapped = self.gensec_client.wrap(test_bytes) test_unwrapped = self.gensec_server.unwrap(test_wrapped) except samba.NTSTATUSError as e: self.fail(str(e)) self.assertEqual(test_bytes, test_unwrapped) test_bytes = b"Hello Client" test_wrapped = self.gensec_server.wrap(test_bytes) test_unwrapped = self.gensec_client.unwrap(test_wrapped) self.assertEqual(test_bytes, test_unwrapped) client_session_key = self.gensec_client.session_key() server_session_key = self.gensec_server.session_key() self.assertEqual(client_session_key, server_session_key)