class KCCTests(samba.tests.TestCase): def setUp(self): super(KCCTests, self).setUp() self.lp = LoadParm() self.creds = Credentials() self.creds.guess(self.lp) self.creds.set_username(os.environ["USERNAME"]) self.creds.set_password(os.environ["PASSWORD"]) def test_list_dsas(self): my_kcc = kcc.KCC(unix_now, False, False, False, False) my_kcc.load_samdb("ldap://%s" % os.environ["SERVER"], self.lp, self.creds) dsas = my_kcc.list_dsas() env = os.environ['TEST_ENV'] for expected_dsa in ENV_DSAS[env]: self.assertIn(expected_dsa, dsas) def test_verify(self): """check that the KCC generates graphs that pass its own verify option. This is not a spectacular achievement when there are only a couple of nodes to connect, but it shows something. """ my_kcc = kcc.KCC(unix_now, readonly=True, verify=True, debug=False, dot_file_dir=None) my_kcc.run("ldap://%s" % os.environ["SERVER"], self.lp, self.creds, attempt_live_connections=False)
def _test_netlogon(self, name, pwd, status, checkFunction): def isLastExpectedMessage(msg): return ( msg["type"] == "Authentication" and msg["Authentication"]["serviceDescription"] == "NETLOGON" and msg["Authentication"]["authDescription"] == "ServerAuthenticate" and msg["Authentication"]["status"] == status) machine_creds = Credentials() machine_creds.guess(self.get_loadparm()) machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) machine_creds.set_password(pwd) machine_creds.set_username(name + "$") try: netlogon.netlogon("ncalrpc:[schannel]", self.get_loadparm(), machine_creds) self.fail("NTSTATUSError not raised") except NTSTATUSError: pass messages = self.waitForMessages(isLastExpectedMessage) checkFunction(messages)
def _test_netlogon(self, binding, checkFunction): def isLastExpectedMessage(msg): return ( msg["type"] == "Authorization" and msg["Authorization"]["serviceDescription"] == "DCE/RPC" and msg["Authorization"]["authType"] == "schannel" and msg["Authorization"]["transportProtection"] == "SEAL") if binding: binding = "[schannel,%s]" % binding else: binding = "[schannel]" machine_creds = Credentials() machine_creds.guess(self.get_loadparm()) machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) machine_creds.set_password(self.machinepass) machine_creds.set_username(self.netbios_name + "$") netlogon_conn = netlogon.netlogon("ncalrpc:%s" % binding, self.get_loadparm(), machine_creds) messages = self.waitForMessages(isLastExpectedMessage, netlogon_conn) checkFunction(messages)
def setUp(self): super(DrsRodcTestCase, self).setUp() self.base_dn = self.ldb_dc1.get_default_basedn() rand = random.randint(1, 10000000) self.ou = "OU=test_drs_rodc%s,%s" % (rand, self.base_dn) self.ldb_dc1.add({ "dn": self.ou, "objectclass": "organizationalUnit" }) self.allowed_group = "CN=Allowed RODC Password Replication Group,CN=Users,%s" % self.base_dn self.site = self.ldb_dc1.server_site_name() self.rodc_name = "TESTRODCDRS%s" % rand self.rodc_pass = "******" self.computer_dn = "CN=%s,OU=Domain Controllers,%s" % (self.rodc_name, self.base_dn) self.rodc_ctx = dc_join(server=self.ldb_dc1.host_dns_name(), creds=self.get_credentials(), lp=self.get_loadparm(), site=self.site, netbios_name=self.rodc_name, targetdir=None, domain=None, machinepass=self.rodc_pass) self._create_rodc(self.rodc_ctx) self.rodc_ctx.create_tmp_samdb() self.tmp_samdb = self.rodc_ctx.tmp_samdb rodc_creds = Credentials() rodc_creds.guess(self.rodc_ctx.lp) rodc_creds.set_username(self.rodc_name+'$') rodc_creds.set_password(self.rodc_pass) self.rodc_creds = rodc_creds (self.drs, self.drs_handle) = self._ds_bind(self.dnsname_dc1) (self.rodc_drs, self.rodc_drs_handle) = self._ds_bind(self.dnsname_dc1, rodc_creds)
class CredentialsOptionsDouble(CredentialsOptions): """Command line options for specifying credentials of two servers.""" def __init__(self, parser): CredentialsOptions.__init__(self, parser) self.no_pass2 = True self.add_option("--simple-bind-dn2", metavar="DN2", action="callback", callback=self._set_simple_bind_dn2, type=str, help="DN to use for a simple bind") self.add_option("--password2", metavar="PASSWORD2", action="callback", help="Password", type=str, callback=self._set_password2) self.add_option("--username2", metavar="USERNAME2", action="callback", type=str, help="Username for second server", callback=self._parse_username2) self.add_option("--workgroup2", metavar="WORKGROUP2", action="callback", type=str, help="Workgroup for second server", callback=self._parse_workgroup2) self.add_option("--no-pass2", action="store_true", help="Don't ask for a password for the second server") self.add_option("--kerberos2", metavar="KERBEROS2", action="callback", type=str, help="Use Kerberos", callback=self._set_kerberos2) self.creds2 = Credentials() def _parse_username2(self, option, opt_str, arg, parser): self.creds2.parse_string(arg) def _parse_workgroup2(self, option, opt_str, arg, parser): self.creds2.set_domain(arg) def _set_password2(self, option, opt_str, arg, parser): self.creds2.set_password(arg) self.no_pass2 = False def _set_kerberos2(self, option, opt_str, arg, parser): if bool(arg) or arg.lower() == "yes": self.creds2.set_kerberos_state(MUST_USE_KERBEROS) else: self.creds2.set_kerberos_state(DONT_USE_KERBEROS) def _set_simple_bind_dn2(self, option, opt_str, arg, parser): self.creds2.set_bind_dn(arg) def get_credentials2(self, lp, guess=True): """Obtain the credentials set on the command-line. :param lp: Loadparm object to use. :param guess: Try guess Credentials from environment :return: Credentials object """ if guess: self.creds2.guess(lp) elif not self.creds2.get_username(): self.creds2.set_anonymous() if self.no_pass2: self.creds2.set_cmdline_callbacks() return self.creds2
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 _get_smb_connection(self, service='SysVol'): # Connect to SMB using kerberos parm = param.LoadParm() creds = Credentials() creds.set_kerberos_state(MUST_USE_KERBEROS) creds.guess(parm) conn = smb.SMB(self._get_server_name(), service, lp=parm, creds=creds) return conn
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/' + 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 join_replicate(ctx): '''replicate the SAM''' print "Starting replication" ctx.local_samdb.transaction_start() try: source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id()) if ctx.ntds_guid is None: print("Using DS_BIND_GUID_W2K3") destination_dsa_guid = misc.GUID(drsuapi.DRSUAPI_DS_BIND_GUID_W2K3) else: destination_dsa_guid = ctx.ntds_guid if ctx.RODC: repl_creds = Credentials() repl_creds.guess(ctx.lp) repl_creds.set_kerberos_state(DONT_USE_KERBEROS) repl_creds.set_username(ctx.samname) repl_creds.set_password(ctx.acct_pass) else: repl_creds = ctx.creds binding_options = "seal" if int(ctx.lp.get("log level")) >= 5: binding_options += ",print" repl = drs_utils.drs_Replicate( "ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options), ctx.lp, repl_creds, ctx.local_samdb) repl.replicate(ctx.schema_dn, source_dsa_invocation_id, destination_dsa_guid, schema=True, rodc=ctx.RODC, replica_flags=ctx.replica_flags) repl.replicate(ctx.config_dn, source_dsa_invocation_id, destination_dsa_guid, rodc=ctx.RODC, replica_flags=ctx.replica_flags) if not ctx.subdomain: repl.replicate(ctx.base_dn, source_dsa_invocation_id, destination_dsa_guid, rodc=ctx.RODC, replica_flags=ctx.domain_replica_flags) if ctx.RODC: repl.replicate(ctx.acct_dn, source_dsa_invocation_id, destination_dsa_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) repl.replicate(ctx.new_krbtgt_dn, source_dsa_invocation_id, destination_dsa_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) ctx.repl = repl ctx.source_dsa_invocation_id = source_dsa_invocation_id ctx.destination_dsa_guid = destination_dsa_guid print "Committing SAM database" except: ctx.local_samdb.transaction_cancel() raise else: ctx.local_samdb.transaction_commit()
def conectar(self): lp = param.LoadParm() badge = Credentials() badge.guess(lp) badge.set_username(self.username) badge.set_password(self.password) cx = SamDB(url='ldap://localhost', lp=lp, credentials=badge) self.domain = cx.domain_dn() return cx
def get_user_creds(self): c = Credentials() c.guess() domain = samba.tests.env_get_var_value('DOMAIN') username = samba.tests.env_get_var_value('USERNAME') password = samba.tests.env_get_var_value('PASSWORD') c.set_domain(domain) c.set_username(username) c.set_password(password) return c
def setUp(self): super(Bug13653Tests, self).setUp() self.env = environ["TEST_ENV"] self.server = environ["SERVER"] self.prefix = environ["PREFIX_ABS"] lp = env_loadparm() creds = Credentials() session = system_session() creds.guess(lp) self.ldb = SamDB(session_info=session, credentials=creds, lp=lp)
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)
class NtlmDisabledTests(TestCase): def setUp(self): super(NtlmDisabledTests, self).setUp() self.lp = self.get_loadparm() self.server = os.getenv("SERVER") self.creds = Credentials() self.creds.guess(self.lp) self.creds.set_username(os.getenv("USERNAME")) self.creds.set_domain(self.server) self.creds.set_password(os.getenv("PASSWORD")) self.creds.set_kerberos_state(DONT_USE_KERBEROS) def tearDown(self): super(NtlmDisabledTests, self).tearDown() def test_ntlm_connection(self): try: conn = srvsvc.srvsvc("ncacn_np:%s[smb2,ntlm]" % self.server, self.lp, self.creds) self.assertIsNotNone(conn) except NTSTATUSError as e: # NTLM might be blocked on this server enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_NTLM_BLOCKED: self.fail("NTLM is disabled on this server") else: raise def test_samr_change_password(self): self.creds.set_kerberos_state(MUST_USE_KERBEROS) conn = samr.samr("ncacn_np:%s[krb5,seal,smb2]" % os.getenv("SERVER")) # we want to check whether this gets rejected outright because NTLM is # disabled, so we don't actually need to encrypt a valid password here server = lsa.String() server.string = self.server username = lsa.String() username.string = os.getenv("USERNAME") try: conn.ChangePasswordUser2(server, username, None, None, True, None, None) except NTSTATUSError as e: # changing passwords should be rejected when NTLM is disabled enum = ctypes.c_uint32(e.args[0]).value if enum == ntstatus.NT_STATUS_NTLM_BLOCKED: self.fail("NTLM is disabled on this server") elif enum == ntstatus.NT_STATUS_WRONG_PASSWORD: # expected error case when NTLM is enabled pass else: raise
def run(): param_samba = { 'basedn' : config.get('samba', 'path'), 'pathsamdb':'%s/sam.ldb' % config.get('samba', 'private'), 'adbase': config.get('samba', 'base') } # SAMDB lp = LoadParm() creds = Credentials() creds.guess(lp) samdb_loc = SamDB(url=param_samba['pathsamdb'], session_info=system_session(),credentials=creds, lp=lp) testpawd = GetPasswordCommand() testpawd.lp = lp passwordattr = config.get('common', 'attr_password') allmail = {} # Search all users for user in samdb_loc.search(base=param_samba['adbase'], expression="(&(objectClass=user)(mail=*))", attrs=["mail","sAMAccountName","pwdLastSet"]): mail = str(user["mail"]) #replace mail if replace_domain in config if config.getboolean('common', 'replace_domain'): mail = mail.split('@')[0] + '@' + config.get('common', 'domain') pwdlastset = user.get('pwdLastSet','') #add mail in all mail allmail[mail] = None if str(pwdlastset) != dict_mail_pwdlastset.get(mail,''): Random.atfork() # Update if password different in dict mail pwdlastset password = testpawd.get_account_attributes(samdb_loc,None,param_samba['basedn'],filter="(sAMAccountName=%s)" % (str(user["sAMAccountName"])),scope=ldb.SCOPE_SUBTREE,attrs=[passwordattr],decrypt=False) if not passwordattr in password: continue password = str(password[passwordattr]) update_password(mail, password, pwdlastset) #delete user found in dict mail pwdlastset but not found in samba listdelete = [] for user in dict_mail_pwdlastset : if not user in allmail: listdelete.append(user) for user in listdelete: del dict_mail_pwdlastset[user] #write new json dict mail password if listdelete: open(filename,'w').write(json.dumps(dict_mail_pwdlastset))
class LdifImportExportTests(samba.tests.TestCaseInTempDir): def setUp(self): super(LdifImportExportTests, self).setUp() self.lp = LoadParm() self.creds = Credentials() self.creds.guess(self.lp) def remove_files(self, *files): for f in files: assert f.startswith(self.tempdir) os.unlink(f) def test_write_search_url(self): pass def test_ldif_to_samdb(self): dburl = os.path.join(self.tempdir, "ldap") samdb = ldif_import_export.ldif_to_samdb(dburl, self.lp, MULTISITE_LDIF) self.assertIsInstance(samdb, SamDB) dsa = ( "CN=WIN01,CN=Servers,CN=Default-First-Site-Name,CN=Sites," "CN=Configuration,DC=ad,DC=samba,DC=example,DC=com" ) res = samdb.search(ldb.Dn(samdb, "CN=NTDS Settings," + dsa), scope=ldb.SCOPE_BASE, attrs=["objectGUID"]) ntds_guid = misc.GUID(samdb.get_ntds_GUID()) self.assertEqual(misc.GUID(res[0]["objectGUID"][0]), ntds_guid) service_name_res = samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"]) dn = ldb.Dn(samdb, service_name_res[0]["dsServiceName"][0]) self.assertEqual(dn, ldb.Dn(samdb, "CN=NTDS Settings," + dsa)) self.remove_files(dburl) def test_ldif_to_samdb_forced_local_dsa(self): for dsa, site in MULTISITE_LDIF_DSAS: dburl = os.path.join(self.tempdir, "ldif-to-samba-forced-local-dsa" "-%s" % dsa) samdb = ldif_import_export.ldif_to_samdb(dburl, self.lp, MULTISITE_LDIF, forced_local_dsa=dsa) self.assertIsInstance(samdb, SamDB) self.assertEqual(samdb.server_site_name(), site) res = samdb.search(ldb.Dn(samdb, "CN=NTDS Settings," + dsa), scope=ldb.SCOPE_BASE, attrs=["objectGUID"]) ntds_guid = misc.GUID(samdb.get_ntds_GUID()) self.assertEqual(misc.GUID(res[0]["objectGUID"][0]), ntds_guid) service_name_res = samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"]) dn = ldb.Dn(samdb, service_name_res[0]["dsServiceName"][0]) self.assertEqual(dn, ldb.Dn(samdb, "CN=NTDS Settings," + dsa)) self.remove_files(dburl) def samdb_to_ldif_file(self): # samdb_to_ldif_file(samdb, dburl, lp, creds, ldif_file): pass
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_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 connection(self): lp = LoadParm() creds = Credentials() creds.guess(lp) creds.set_username("") creds.set_password("") con = SamDB(url='ldap://192.168.100.26:389', session_info=system_session(), credentials=creds, lp=lp) return con
def __init__(self): self.configRegistry = ConfigRegistry() self.configRegistry.load() lp = LoadParm() creds = Credentials() creds.guess(lp) self.samdb = SamDB(url='/var/lib/samba/private/sam.ldb', session_info=system_session(), credentials=creds, lp=lp)
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)
class NtlmDisabledTests(TestCase): def setUp(self): super(NtlmDisabledTests, self).setUp() self.lp = self.get_loadparm() self.server = os.getenv("SERVER") self.creds = Credentials() self.creds.guess(self.lp) self.creds.set_username(os.getenv("USERNAME")) self.creds.set_domain(self.server) self.creds.set_password(os.getenv("PASSWORD")) self.creds.set_kerberos_state(DONT_USE_KERBEROS) def tearDown(self): super(NtlmDisabledTests, self).tearDown() def test_ntlm_connection(self): try: conn = srvsvc.srvsvc("ncacn_np:%s[smb2,ntlm]" % self.server, self.lp, self.creds) self.assertIsNotNone(conn) except NTSTATUSError as e: # NTLM might be blocked on this server enum = ctypes.c_uint32(e[0]).value if enum == ntstatus.NT_STATUS_NTLM_BLOCKED: self.fail("NTLM is disabled on this server") else: raise def test_samr_change_password(self): self.creds.set_kerberos_state(MUST_USE_KERBEROS) conn = samr.samr("ncacn_np:%s[krb5,seal,smb2]" % os.getenv("SERVER")) # we want to check whether this gets rejected outright because NTLM is # disabled, so we don't actually need to encrypt a valid password here server = lsa.String() server.string = self.server username = lsa.String() username.string = os.getenv("USERNAME") try: conn.ChangePasswordUser2(server, username, None, None, True, None, None) except NTSTATUSError as e: # changing passwords should be rejected when NTLM is disabled enum = ctypes.c_uint32(e[0]).value if enum == ntstatus.NT_STATUS_NTLM_BLOCKED: self.fail("NTLM is disabled on this server") elif enum == ntstatus.NT_STATUS_WRONG_PASSWORD: # expected error case when NTLM is enabled pass else: raise
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_find_key_param(self): paths = get_paths(param, None, smb_conf_path) creds = Credentials() lp = env_loadparm() creds.guess(lp) rootdn = "dc=samba,dc=example,dc=com" ldbs = get_ldbs(paths, creds, system_session(), lp) names = find_provision_key_parameters(ldbs.sam, ldbs.secrets, ldbs.idmap, paths, smb_conf_path, lp) self.assertEquals(names.realm, "SAMBA.EXAMPLE.COM") self.assertEquals(str(names.rootdn).lower(), rootdn.lower()) self.assertNotEquals(names.policyid_dc, None) self.assertNotEquals(names.ntdsguid, "")
def main(): args = parse_args() logging.basicConfig(level=logging.DEBUG if args.debug else logging.WARNING) inpipe = sys.stdin outpipe = sys.stdout if args.unix: import socket try: os.remove(args.unix) except OSError: pass sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.bind(args.unix) os.chmod(args.unix, 0o777) logger.debug("Bound unix socket: {}".format(args.unix)) logger.info("Waiting for connection at {}".format(args.unix)) sock.listen(1) csock, client_address = sock.accept() logger.info("Accepted connection from {}".format(client_address)) inpipe = outpipe = csock.makefile() lp = LoadParm() lp.load_default() creds = Credentials() creds.guess(lp) creds.set_kerberos_state(MUST_USE_KERBEROS) # If MUST_USE_KERBEROS and we have no ticket, yields this error: # "Failed to connect to 'ldap://dc1' with backend 'ldap': LDAP client # internal error: NT_STATUS_INVALID_PARAMETER" # lp is required by ldap_connect_send() -> lpcfg_resolve_context() samdb = SamDB(lp=lp, url=args.url, credentials=creds) logger.debug("Opened SAM DB:") logger.debug(" domain_dn: {}".format(samdb.domain_dn())) logger.debug(" domain_dns_name: {}".format(samdb.domain_dns_name())) try: r = SambaResponder(samdb, inpipe, outpipe) r.run() finally: if args.unix: try: os.remove(args.unix) except OSError: pass
def test_msDSRevealedUsers_using_other_RODC(self): """ Ensure that the machine account is tied to the destination DSA. """ # Create a new identical RODC with just the first letter missing other_rodc_name = self.rodc_name[1:] other_rodc_ctx = dc_join(server=self.ldb_dc1.host_dns_name(), creds=self.get_credentials(), lp=self.get_loadparm(), site=self.site, netbios_name=other_rodc_name, targetdir=None, domain=None, machinepass=self.rodc_pass) self._create_rodc(other_rodc_ctx) other_rodc_creds = Credentials() other_rodc_creds.guess(other_rodc_ctx.lp) other_rodc_creds.set_username(other_rodc_name+'$') other_rodc_creds.set_password(self.rodc_pass) (other_rodc_drs, other_rodc_drs_handle) = self._ds_bind(self.dnsname_dc1, other_rodc_creds) rand = random.randint(1, 10000000) expected_user_attributes = [drsuapi.DRSUAPI_ATTID_lmPwdHistory, drsuapi.DRSUAPI_ATTID_supplementalCredentials, drsuapi.DRSUAPI_ATTID_ntPwdHistory, drsuapi.DRSUAPI_ATTID_unicodePwd, drsuapi.DRSUAPI_ATTID_dBCSPwd] user_name = "test_rodcF_%s" % rand user_dn = "CN=%s,%s" % (user_name, self.ou) self.ldb_dc1.add({ "dn": user_dn, "objectclass": "user", "sAMAccountName": user_name }) # Store some secret on this user self.ldb_dc1.setpassword("(sAMAccountName=%s)" % user_name, 'penguin12#', False, user_name) self.ldb_dc1.add_remove_group_members("Allowed RODC Password Replication Group", [user_name], add_members_operation=True) req10 = self._getnc_req10(dest_dsa=str(other_rodc_ctx.ntds_guid), invocation_id=self.ldb_dc1.get_invocation_id(), nc_dn_str=user_dn, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, partial_attribute_set=drs_get_rodc_partial_attribute_set(self.ldb_dc1, self.tmp_samdb), max_objects=133, replica_flags=0) try: (level, ctr) = self.rodc_drs.DsGetNCChanges(self.rodc_drs_handle, 10, req10) self.fail("Successfully replicated secrets to an RODC that shouldn't have been replicated.") except WERRORError as (enum, estr): self.assertEquals(enum, 8630) # ERROR_DS_DRA_SECRETS_DENIED
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 get_service_creds(self, allow_missing_password=False): c = Credentials() c.guess() domain = samba.tests.env_get_var_value('DOMAIN') realm = samba.tests.env_get_var_value('REALM') username = samba.tests.env_get_var_value('SERVICE_USERNAME') password = samba.tests.env_get_var_value( 'SERVICE_PASSWORD', allow_missing=allow_missing_password) c.set_domain(domain) c.set_realm(realm) c.set_username(username) if password is not None: c.set_password(password) return c
def samdb_connect(): """ Open and return a SamDB connection """ with root(): lp = samba.param.LoadParm() lp.load("/etc/samba/smb.conf") creds = Credentials() creds.guess(lp) session = system_session() samdb = SamDB("/var/lib/samba/private/sam.ldb", session_info=session, credentials=creds, lp=lp) return samdb
def create_account(self, name, machine_account=False, spn=None, upn=None): '''Create an account for testing. The dn of the created account is added to self.accounts, which is used by tearDown to clean up the created accounts. ''' dn = "cn=%s,%s" % (name, self.ldb.domain_dn()) # remove the account if it exists, this will happen if a previous test # run failed delete_force(self.ldb, dn) if machine_account: object_class = "computer" account_name = "%s$" % name account_control = str(UF_WORKSTATION_TRUST_ACCOUNT) else: object_class = "user" account_name = name account_control = str(UF_NORMAL_ACCOUNT) password = generate_random_password(32, 32) utf16pw = ('"%s"' % password).encode('utf-16-le') details = { "dn": dn, "objectclass": object_class, "sAMAccountName": account_name, "userAccountControl": account_control, "unicodePwd": utf16pw } if spn is not None: details["servicePrincipalName"] = spn if upn is not None: details["userPrincipalName"] = upn self.ldb.add(details) creds = Credentials() creds.guess(self.lp) creds.set_realm(self.ldb.domain_dns_name().upper()) creds.set_domain(self.ldb.domain_netbios_name().upper()) creds.set_password(password) creds.set_username(account_name) if machine_account: creds.set_workstation(name) # # Save the account name so it can be deleted in the tearDown self.accounts.append(dn) return (creds, dn)
def join_replicate(ctx): '''replicate the SAM''' print "Starting replication" ctx.local_samdb.transaction_start() try: source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id()) destination_dsa_guid = ctx.ntds_guid if ctx.RODC: repl_creds = Credentials() repl_creds.guess(ctx.lp) repl_creds.set_kerberos_state(DONT_USE_KERBEROS) repl_creds.set_username(ctx.samname) repl_creds.set_password(ctx.acct_pass) else: repl_creds = ctx.creds binding_options = "seal" if ctx.lp.get("debug level") >= 5: binding_options += ",print" repl = drs_utils.drs_Replicate( "ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options), ctx.lp, repl_creds, ctx.local_samdb) repl.replicate(ctx.schema_dn, source_dsa_invocation_id, destination_dsa_guid, schema=True, rodc=ctx.RODC, replica_flags=ctx.replica_flags) repl.replicate(ctx.config_dn, source_dsa_invocation_id, destination_dsa_guid, rodc=ctx.RODC, replica_flags=ctx.replica_flags) repl.replicate(ctx.base_dn, source_dsa_invocation_id, destination_dsa_guid, rodc=ctx.RODC, replica_flags=ctx.replica_flags) if ctx.RODC: repl.replicate(ctx.acct_dn, source_dsa_invocation_id, destination_dsa_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) repl.replicate(ctx.new_krbtgt_dn, source_dsa_invocation_id, destination_dsa_guid, exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) print "Committing SAM database" except: ctx.local_samdb.transaction_cancel() raise else: ctx.local_samdb.transaction_commit()
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)
class EncryptedSecretsTests(TestCase): def setUp(self): super(EncryptedSecretsTests, self).setUp() self.lp = samba.tests.env_loadparm() self.creds = Credentials() self.session = system_session() self.creds.guess(self.lp) self.session = system_session() self.ldb = SamDB(session_info=self.session, credentials=self.creds, lp=self.lp) def test_encrypted_secrets(self): """Test that secret attributes are stored encrypted on disk""" basedn = self.ldb.domain_dn() backend_filename = "%s.ldb" % basedn.upper() backend_subpath = os.path.join("sam.ldb.d", backend_filename) backend_path = self.lp.private_path(backend_subpath) backenddb = ldb.Ldb("ldb://" + backend_path, flags=ldb.FLG_DONT_CREATE_DB) dn = "CN=Administrator,CN=Users,%s" % basedn res = backenddb.search(scope=ldb.SCOPE_BASE, base=dn, attrs=["unicodePwd"]) self.assertIs(True, len(res) > 0) obj = res[0] blob = obj["unicodePwd"][0] self.assertTrue(len(blob) > 30) # Now verify that the header contains the correct magic value. encrypted = ndr_unpack(drsblobs.EncryptedSecret, blob) magic = 0xca5caded self.assertEquals(magic, encrypted.header.magic) def test_required_features(self): """Test that databases are provisioned with encryptedSecrets as a required feature """ res = self.ldb.search(scope=ldb.SCOPE_BASE, base="@SAMBA_DSDB", attrs=["requiredFeatures"]) self.assertTrue(len(res) > 0) self.assertTrue("requiredFeatures" in res[0]) required_features = res[0]["requiredFeatures"] self.assertTrue("encryptedSecrets" in required_features)
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)
class EncryptedSecretsTests(TestCase): def setUp(self): super(EncryptedSecretsTests, self).setUp() self.lp = samba.tests.env_loadparm() self.creds = Credentials() self.session = system_session() self.creds.guess(self.lp) self.session = system_session() self.ldb = SamDB(session_info=self.session, credentials=self.creds, lp=self.lp) def test_encrypted_secrets(self): """Test that secret attributes are stored encrypted on disk""" basedn = self.ldb.domain_dn() backend_filename = "%s.ldb" % basedn.upper() backend_subpath = os.path.join("sam.ldb.d", backend_filename) backend_path = self.lp.private_path(backend_subpath) backenddb = ldb.Ldb("ldb://" + backend_path, flags=ldb.FLG_DONT_CREATE_DB) dn = "CN=Administrator,CN=Users,%s" % basedn res = backenddb.search(scope=ldb.SCOPE_BASE, base=dn, attrs=["unicodePwd"]) self.assertIs(True, len(res) > 0) obj = res[0] blob = obj["unicodePwd"][0] self.assertTrue(len(blob) > 30) # Now verify that the header contains the correct magic value. encrypted = ndr_unpack(drsblobs.EncryptedSecret, blob) magic = 0xca5caded self.assertEquals(magic, encrypted.header.magic) def test_required_features(self): """Test that databases are provisioned with encryptedSecrets as a required feature """ res = self.ldb.search(scope=ldb.SCOPE_BASE, base="@SAMBA_DSDB", attrs=["requiredFeatures"]) self.assertTrue(len(res) > 0) self.assertTrue("requiredFeatures" in res[0]) required_features = res[0]["requiredFeatures"] self.assertTrue(b"encryptedSecrets" in required_features)
def authenticate(self, usuario, password): # Connect to samba and attempt to authenticate this user print("SambaServer.authenticate: authenticating with %s and %s" % (usuario, password)) lp = param.LoadParm() badge = Credentials() badge.guess(lp) badge.set_username(usuario) badge.set_password(password) # Intento la conexion. cx = SamDB(url='ldap://localhost', lp=lp, credentials=badge) print("cx returned: %s" % cx) # Get the domain from the SamDB and store it self.domain = cx.domain_dn() # Listo, la gracia es que si logre autenticarme con estos datos, y hay algun # resultado de mis acciones, voy a devolver algo. return cx
def __init_samba_params(self, root_use_machine_creds=True): lp = samba.param.LoadParm() try: lp.load_default() except Exception as e: raise RuntimeError("cannot load default samba parameters", e) creds = Credentials() creds.guess(lp) if os.getuid( ) == 0 and root_use_machine_creds: # use machine credentials # creds.set_machine_account(lp) self.use_machine_creds = True self.lp = lp self.realm = lp.get('realm') self.base_dn = r2dn(self.realm) self.creds = creds
class DsdbFullScanTests(TestCase): def setUp(self): super(DsdbFullScanTests, self).setUp() self.lp = samba.tests.env_loadparm() self.creds = Credentials() self.creds.guess(self.lp) self.session = system_session() def test_sam_ldb_open_no_full_scan(self): try: self.samdb = SamDB( session_info=self.session, credentials=self.creds, lp=self.lp, options=["disable_full_db_scan_for_self_test:1"]) except ldb.LdbError as err: estr = err.args[1] self.fail("sam.ldb required a full scan to start up")
def netlogon(self): server = os.environ["SERVER"] host = os.environ["SERVER_IP"] lp = self.get_loadparm() credentials = self.get_credentials() session = system_session() ldb = SamDB(url="ldap://%s" % host, session_info=session, credentials=credentials, lp=lp) machine_pass = samba.generate_random_password(32, 32) machine_name = MACHINE_NAME machine_dn = "cn=%s,%s" % (machine_name, ldb.domain_dn()) delete_force(ldb, machine_dn) utf16pw = ('"%s"' % get_string(machine_pass)).encode('utf-16-le') ldb.add({ "dn": machine_dn, "objectclass": "computer", "sAMAccountName": "%s$" % machine_name, "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), "unicodePwd": utf16pw }) machine_creds = Credentials() machine_creds.guess(lp) machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) machine_creds.set_kerberos_state(DONT_USE_KERBEROS) machine_creds.set_password(machine_pass) machine_creds.set_username(machine_name + "$") machine_creds.set_workstation(machine_name) netlogon.netlogon("ncacn_ip_tcp:%s[schannel,seal]" % server, lp, machine_creds) delete_force(ldb, machine_dn)
class DsdbFullScanTests(TestCase): def setUp(self): super(DsdbFullScanTests, self).setUp() self.lp = samba.tests.env_loadparm() self.creds = Credentials() self.creds.guess(self.lp) self.session = system_session() def test_sam_ldb_open_no_full_scan(self): try: self.samdb = SamDB(session_info=self.session, credentials=self.creds, lp=self.lp, options=["disable_full_db_scan_for_self_test:1"]) except LdbError as err: estr = err.args[1] self.fail("sam.ldb required a full scan to start up")
def get_ad_binddn_from_name(base, server, username, password): lp = LoadParm() creds = Credentials() creds.guess(lp) creds.set_username(username) creds.set_password(password) binddn = 'cn=%s,cn=users,%s' % (ldap.dn.escape_dn_chars(username), base) try: samdb = SamDB(url='ldap://%s' % server, session_info=system_session(), credentials=creds, lp=lp) res = samdb.search( base, scope=ldb.SCOPE_SUBTREE, expression=ldap.filter.filter_format('(samAccountName=%s)', [username, ]), attrs=['samaccountname']) if res.count == 1: binddn = res.msgs[0].get('dn', idx=0).extended_str() except ldb.LdbError as ex: MODULE.warn('get_dn_from_name() could not get binddn for user %s: %s' % (username, ex)) return binddn
class KCCTests(samba.tests.TestCase): def setUp(self): super(KCCTests, self).setUp() self.lp = LoadParm() self.creds = Credentials() self.creds.guess(self.lp) self.creds.set_username(os.environ["USERNAME"]) self.creds.set_password(os.environ["PASSWORD"]) def test_list_dsas(self): my_kcc = kcc.KCC(unix_now, False, False, False, False) my_kcc.load_samdb("ldap://%s" % os.environ["SERVER"], self.lp, self.creds) try: dsas = my_kcc.list_dsas() except kcc.KCCError as e: self.fail("kcc.list_dsas failed with %s" % e) env = os.environ['TEST_ENV'] for expected_dsa in ENV_DSAS[env]: self.assertIn(expected_dsa, dsas) def test_verify(self): """check that the KCC generates graphs that pass its own verify option. This is not a spectacular achievement when there are only a couple of nodes to connect, but it shows something. """ my_kcc = kcc.KCC(unix_now, readonly=True, verify=True, debug=False, dot_file_dir=None) # As this is flapping with errors under python3, we catch # exceptions and turn them into failures.. try: my_kcc.run("ldap://%s" % os.environ["SERVER"], self.lp, self.creds, attempt_live_connections=False) except (samba.kcc.graph_utils.GraphError, kcc.KCCError): import traceback traceback.print_exc() self.fail()
def get_dns_zones(): request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY server = '127.0.0.1' binding_str = 'ncacn_ip_tcp:%s[sign]' % server cred_data = open('/vapour/dnsquery').read().split(':') creds = Credentials() creds.guess(lp) creds.set_username(cred_data[0]) creds.set_password(cred_data[1].rstrip()) dns_conn = dnsserver.dnsserver(binding_str, lp, creds) client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN typeid, res = dns_conn.DnssrvComplexOperation2( client_version, 0, server, None, 'EnumZones', dnsserver.DNSSRV_TYPEID_DWORD, request_filter) return dict(res)
def run(): param_samba = { 'basedn' : config.get('samba', 'path'), 'pathsamdb':'%s/sam.ldb' % config.get('samba', 'private'), 'adbase': config.get('samba', 'base') } # SAMDB lp = LoadParm() creds = Credentials() creds.guess(lp) samdb_loc = SamDB(url=param_samba['pathsamdb'], session_info=system_session(),credentials=creds, lp=lp) testpawd = GetPasswordCommand() testpawd.lp = lp allmail = {} # Search all users for user in samdb_loc.search(base=param_samba['adbase'], expression="(&(objectClass=user)(!(objectClass=computer)))", attrs=["mail","sAMAccountName",'userAccountControl','distinguishedName']): mail = str(user.get('mail','')) #replace mail if replace_domain in config if config.getboolean('common', 'replace_domain'): if mail != '': mail = mail.split('@')[0] + '@' + config.get('common', 'domain') uac = user['userAccountControl'] username = str(user["sAMAccountName"]) dn = str(user["distinguishedName"]) #add mail in all mail allmail[mail] = None Random.atfork() password = testpawd.get_account_attributes(samdb_loc,None,param_samba['basedn'],filter="(sAMAccountName=%s)" % (username),scope=ldb.SCOPE_SUBTREE,attrs=['virtualClearTextUTF8'],decrypt=False) if not 'virtualClearTextUTF8' in password: continue password = str(password['virtualClearTextUTF8']) update_password(mail, password, uac,dn,username,samdb_loc)
def getUsers(self): lp = param.LoadParm() badge = Credentials() badge.guess(lp) badge.set_username('Administrator') badge.set_password('pa$$w0rd!') print("Getting users") # Binding... cx = SamDB(url='ldap://localhost', lp=lp, credentials=badge) # Search... search_result = cx.search('DC=kajohansen,DC=com', scope=2, expression='(objectClass=user)', attrs=["samaccountname"]) users = [] # list to hold our users # Results... for username in search_result: # print("User: %s" % username.get("samaccountname", idx=0)) users.append(username.get("samaccountname", idx=0)) return users
def run(): sambaPrivate = config.get("samba", "private") sambaPath = config.get("samba", "path") adBase = config.get("samba", "base") creds = Credentials() samdb = SamDB( url=(sambaPrivate + "/sam.ldb.d/" + sambaPath + ".ldb"), session_info=system_session(), credentials=creds.guess(), ) res = samdb.search( base=adBase, expression="(objectClass=user)", attrs=["supplementalCredentials", "sAMAccountName", "mail"] ) for r in res: if not "supplementalCredentials" in r: sys.stderr.write("%s: no supplementalCredentials\n" % str(r["dn"])) continue scb = ndr_unpack(drsblobs.supplementalCredentialsBlob, str(r["supplementalCredentials"])) for p in scb.sub.packages: if p.name == "Primary:CLEARTEXT": update_password(str(r["mail"]), binascii.unhexlify(p.data).decode("utf16"))
def test_get_ldbs(self): paths = get_paths(param, None, smb_conf_path) creds = Credentials() lp = env_loadparm() creds.guess(lp) get_ldbs(paths, creds, system_session(), lp)
class RodcCmdTestCase(SambaToolCmdTest): def setUp(self): super(RodcCmdTestCase, self).setUp() self.lp = samba.param.LoadParm() self.lp.load(os.environ["SMB_CONF_PATH"]) self.creds = Credentials() self.creds.set_username(os.environ["DC_USERNAME"]) self.creds.set_password(os.environ["DC_PASSWORD"]) self.creds.guess(self.lp) self.session = system_session() self.ldb = SamDB("ldap://" + os.environ["DC_SERVER"], session_info=self.session, credentials=self.creds,lp=self.lp) self.base_dn = self.ldb.domain_dn() self.ldb.newuser("sambatool1", "1qazXSW@") self.ldb.newuser("sambatool2", "2wsxCDE#") self.ldb.newuser("sambatool3", "3edcVFR$") self.ldb.newuser("sambatool4", "4rfvBGT%") self.ldb.newuser("sambatool5", "5tjbNHY*") self.ldb.newuser("sambatool6", "6yknMJU*") self.ldb.add_remove_group_members("Allowed RODC Password Replication Group", ["sambatool1", "sambatool2", "sambatool3", "sambatool4", "sambatool5"], add_members_operation=True) def tearDown(self): super(RodcCmdTestCase, self).tearDown() self.ldb.deleteuser("sambatool1") self.ldb.deleteuser("sambatool2") self.ldb.deleteuser("sambatool3") self.ldb.deleteuser("sambatool4") self.ldb.deleteuser("sambatool5") self.ldb.deleteuser("sambatool6") (result, out, err) = self.runsubcmd("drs", "replicate", "--local", "unused", os.environ["DC_SERVER"], self.base_dn) def test_single_by_account_name(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\n" % self.base_dn) self.assertEqual(err, "") def test_single_by_dn(self): (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool2,cn=users,%s" % self.base_dn, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool2,CN=Users,%s\n" % self.base_dn) def test_multi_by_account_name(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", "sambatool2", "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) def test_multi_by_dn(self): (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool3,cn=users,%s" % self.base_dn, "cn=sambatool4,cn=users,%s" % self.base_dn, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool3,CN=Users,%s\nReplicating DN CN=sambatool4,CN=Users,%s\n" % (self.base_dn, self.base_dn)) def test_multi_in_file(self): tempf = os.path.join(self.tempdir, "accountlist") open(tempf, 'w').write("sambatool1\nsambatool2") (result, out, err) = self.runsubcmd("rodc", "preload", "--file", tempf, "--server", os.environ["DC_SERVER"]) self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) os.unlink(tempf) def test_multi_with_missing_name_success(self): (result, out, err) = self.runsubcmd("rodc", "preload", "nonexistentuser1", "sambatool5", "nonexistentuser2", "--server", os.environ["DC_SERVER"], "--ignore-errors") self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertTrue(out.startswith("Replicating DN CN=sambatool5,CN=Users,%s\n" % self.base_dn)) def test_multi_with_missing_name_failure(self): (result, out, err) = self.runsubcmd("rodc", "preload", "nonexistentuser1", "sambatool5", "nonexistentuser2", "--server", os.environ["DC_SERVER"]) self.assertCmdFail(result, "ensuring rodc prefetch quit on missing user") def test_multi_without_group_success(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool6", "sambatool5", "--server", os.environ["DC_SERVER"], "--ignore-errors") self.assertCmdSuccess(result, out, err, "ensuring rodc prefetch ran successfully") self.assertTrue(out.startswith("Replicating DN CN=sambatool6,CN=Users,%s\n" "Replicating DN CN=sambatool5,CN=Users,%s\n" % (self.base_dn, self.base_dn))) def test_multi_without_group_failure(self): (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool6", "sambatool5", "--server", os.environ["DC_SERVER"]) self.assertCmdFail(result, "ensuring rodc prefetch quit on non-replicated user")
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
class KCCMultisiteLdifTests(samba.tests.TestCaseInTempDir): def setUp(self): super(KCCMultisiteLdifTests, self).setUp() self.lp = LoadParm() self.creds = Credentials() self.creds.guess(self.lp) def remove_files(self, *files): for f in files: assert(f.startswith(self.tempdir)) os.unlink(f) def _get_kcc(self, name, readonly=False, verify=False, dot_file_dir=None): # Note that setting read-only to False won't affect the ldif, # only the temporary database that is created from it. my_kcc = KCC(unix_now, readonly=readonly, verify=verify, dot_file_dir=dot_file_dir) tmpdb = os.path.join(self.tempdir, 'tmpdb') my_kcc.import_ldif(tmpdb, self.lp, self.creds, MULTISITE_LDIF) self.remove_files(tmpdb) return my_kcc def test_list_dsas(self): my_kcc = self._get_kcc('test-list') dsas = set(my_kcc.list_dsas()) expected_dsas = set(x[0] for x in MULTISITE_LDIF_DSAS) self.assertEqual(dsas, expected_dsas) def test_verify(self): """Check that the KCC generates graphs that pass its own verify option. """ my_kcc = self._get_kcc('test-verify', verify=True) tmpdb = os.path.join(self.tempdir, 'verify-tmpdb') my_kcc.import_ldif(tmpdb, self.lp, self.creds, MULTISITE_LDIF) my_kcc.run("ldap://%s" % tmpdb, self.lp, self.creds, attempt_live_connections=False) self.remove_files(tmpdb) def test_dotfiles(self): """Check that KCC writes dot_files when asked. """ my_kcc = self._get_kcc('test-dotfiles', dot_file_dir=self.tempdir) tmpdb = os.path.join(self.tempdir, 'dotfile-tmpdb') files = [tmpdb] my_kcc.import_ldif(tmpdb, self.lp, self.creds, MULTISITE_LDIF) my_kcc.run("ldap://%s" % tmpdb, self.lp, self.creds, attempt_live_connections=False) dot = '/usr/bin/dot' for fn in os.listdir(self.tempdir): if fn.endswith('.dot'): ffn = os.path.join(self.tempdir, fn) if os.path.exists(dot) and subprocess.call([dot, '-?']) == 0: r = subprocess.call([dot, '-Tcanon', ffn]) self.assertEqual(r, 0) #even if dot is not there, at least check the file is non-empty size = os.stat(ffn).st_size self.assertNotEqual(size, 0) files.append(ffn) self.remove_files(*files)
if len(userlist) != len(user_sids): raise ProvisioningError("Please remove duplicate user sid entries before upgrade.") common_sids = group_sids.intersection(user_sids) if common_sids: logger.error("Following sids are both user and group sids:") for sid in common_sids: logger.error(" %s" % str(sid)) raise ProvisioningError("Please remove duplicate sid entries before upgrade.") # Get posix attributes from ldap or the os homes = {} shells = {} pgids = {} if ldap: creds = Credentials() creds.guess(samba3.lp) creds.set_bind_dn(ldapuser) creds.set_password(ldappass) urls = samba3.lp.get("passdb backend").split(":",1)[1].strip('"') for url in urls.split(): try: ldb_object = Ldb(url, credentials=creds) except ldb.LdbError, e: raise ProvisioningError("Could not open ldb connection to %s, the error message is: %s" % (url, e)) else: break logger.info("Exporting posix attributes") userlist = s3db.search_users(0) for entry in userlist: username = entry['account_name'] if username in uids.keys():
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 DsdbTests(TestCase): def setUp(self): super(DsdbTests, self).setUp() self.lp = samba.param.LoadParm() self.lp.load(os.path.join(os.path.join(self.baseprovpath(), "etc"), "smb.conf")) self.creds = Credentials() self.creds.guess(self.lp) self.session = system_session() self.samdb = SamDB(os.path.join(self.baseprovpath(), "private", "sam.ldb"), session_info=self.session, credentials=self.creds,lp=self.lp) def baseprovpath(self): return os.path.join(os.environ['SELFTEST_PREFIX'], "ad_dc_ntvfs") def test_get_oid_from_attrid(self): oid = self.samdb.get_oid_from_attid(591614) self.assertEquals(oid, "1.2.840.113556.1.4.1790") def test_error_replpropertymetadata(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) ctr = repl.ctr for o in ctr.array: # Search for Description if o.attid == 13: old_version = o.version o.version = o.version + 1 replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"]) def test_error_replpropertymetadata_nochange(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"]) def test_error_replpropertymetadata_allow_sort(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.samdb.modify(msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0", "local_oid:1.3.6.1.4.1.7165.4.3.25:0"]) def test_twoatt_replpropertymetadata(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData", "uSNChanged"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) ctr = repl.ctr for o in ctr.array: # Search for Description if o.attid == 13: old_version = o.version o.version = o.version + 1 o.local_usn = long(str(res[0]["uSNChanged"])) + 1 replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") msg["description"] = ldb.MessageElement("new val", ldb.FLAG_MOD_REPLACE, "description") self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"]) def test_set_replpropertymetadata(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["replPropertyMetaData", "uSNChanged"]) repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(res[0]["replPropertyMetaData"])) ctr = repl.ctr for o in ctr.array: # Search for Description if o.attid == 13: old_version = o.version o.version = o.version + 1 o.local_usn = long(str(res[0]["uSNChanged"])) + 1 o.originating_usn = long(str(res[0]["uSNChanged"])) + 1 replBlob = ndr_pack(repl) msg = ldb.Message() msg.dn = res[0].dn msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData") self.samdb.modify(msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"]) def test_ok_get_attribute_from_attid(self): self.assertEquals(self.samdb.get_attribute_from_attid(13), "description") def test_ko_get_attribute_from_attid(self): self.assertEquals(self.samdb.get_attribute_from_attid(11979), None) def test_get_attribute_replmetadata_version(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["dn"]) self.assertEquals(len(res), 1) dn = str(res[0].dn) self.assertEqual(self.samdb.get_attribute_replmetadata_version(dn, "unicodePwd"), 1) def test_set_attribute_replmetadata_version(self): res = self.samdb.search(expression="cn=Administrator", scope=ldb.SCOPE_SUBTREE, attrs=["dn"]) self.assertEquals(len(res), 1) dn = str(res[0].dn) version = self.samdb.get_attribute_replmetadata_version(dn, "description") self.samdb.set_attribute_replmetadata_version(dn, "description", version + 2) self.assertEqual(self.samdb.get_attribute_replmetadata_version(dn, "description"), version + 2)
class UpgradeProvisionWithLdbTestCase(TestCaseInTempDir): def _getEmptyDbName(self): return os.path.join(self.tempdir, "sam.ldb") def setUp(self): super(UpgradeProvisionWithLdbTestCase, self).setUp() paths = get_paths(param, None, smb_conf_path) self.creds = Credentials() self.lp = env_loadparm() self.creds.guess(self.lp) self.paths = paths self.ldbs = get_ldbs(paths, self.creds, system_session(), self.lp) self.names = find_provision_key_parameters(self.ldbs.sam, self.ldbs.secrets, self.ldbs.idmap, paths, smb_conf_path, self.lp) self.referencedb = create_dummy_secretsdb( os.path.join(self.tempdir, "ref.ldb")) def test_search_constructed_attrs_stored(self): hashAtt = search_constructed_attrs_stored(self.ldbs.sam, self.names.rootdn, ["msds-KeyVersionNumber"]) self.assertFalse(hashAtt.has_key("msds-KeyVersionNumber")) def test_increment_calculated_keyversion_number(self): dn = "CN=Administrator,CN=Users,%s" % self.names.rootdn # We conctruct a simple hash for the user administrator hash = {} # And we want the version to be 140 hash[dn.lower()] = 140 increment_calculated_keyversion_number(self.ldbs.sam, self.names.rootdn, hash) self.assertEqual(self.ldbs.sam.get_attribute_replmetadata_version(dn, "unicodePwd"), 140) # This function should not decrement the version hash[dn.lower()] = 130 increment_calculated_keyversion_number(self.ldbs.sam, self.names.rootdn, hash) self.assertEqual(self.ldbs.sam.get_attribute_replmetadata_version(dn, "unicodePwd"), 140) def test_identic_rename(self): rootdn = "DC=samba,DC=example,DC=com" guestDN = ldb.Dn(self.ldbs.sam, "CN=Guest,CN=Users,%s" % rootdn) identic_rename(self.ldbs.sam, guestDN) res = self.ldbs.sam.search(expression="(name=Guest)", base=rootdn, scope=ldb.SCOPE_SUBTREE, attrs=["dn"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0]["dn"]), "CN=Guest,CN=Users,%s" % rootdn) def test_delta_update_basesamdb(self): dummysampath = self._getEmptyDbName() delta_update_basesamdb(self.paths.samdb, dummysampath, self.creds, system_session(), self.lp, dummymessage) def test_update_gpo_simple(self): dir = getpolicypath(self.paths.sysvol, self.names.dnsdomain, self.names.policyid) shutil.rmtree(dir) self.assertFalse(os.path.isdir(dir)) update_gpo(self.paths, self.ldbs.sam, self.names, self.lp, dummymessage) self.assertTrue(os.path.isdir(dir)) def test_update_gpo_acl(self): path = os.path.join(self.tempdir, "testupdategpo") save = self.paths.sysvol self.paths.sysvol = path os.mkdir(path) os.mkdir(os.path.join(path, self.names.dnsdomain)) os.mkdir(os.path.join(os.path.join(path, self.names.dnsdomain), "Policies")) update_gpo(self.paths, self.ldbs.sam, self.names, self.lp, dummymessage) shutil.rmtree(path) self.paths.sysvol = save def test_getOEMInfo(self): realm = self.lp.get("realm") basedn = "DC=%s" % realm.replace(".", ", DC=") oem = getOEMInfo(self.ldbs.sam, basedn) self.assertNotEquals(oem, "") def test_update_dns_account(self): update_dns_account_password(self.ldbs.sam, self.ldbs.secrets, self.names) def test_updateOEMInfo(self): realm = self.lp.get("realm") basedn = "DC=%s" % realm.replace(".", ", DC=") oem = getOEMInfo(self.ldbs.sam, basedn) updateOEMInfo(self.ldbs.sam, basedn) oem2 = getOEMInfo(self.ldbs.sam, basedn) self.assertNotEquals(str(oem), str(oem2)) self.assertTrue(re.match(".*upgrade to.*", str(oem2))) def tearDown(self): for name in ["ref.ldb", "secrets.ldb", "sam.ldb"]: path = os.path.join(self.tempdir, name) if os.path.exists(path): os.unlink(path) super(UpgradeProvisionWithLdbTestCase, self).tearDown()