def set_attribute_with_provision_ctrl(self, dn, key, value):
     LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16'
     DSDB_CONTROL_REPLICATED_UPDATE_OID = '1.3.6.1.4.1.7165.4.3.3'
     ctrls = [
         LDAPControl(LDB_CONTROL_PROVISION_OID, criticality=0),
         LDAPControl(DSDB_CONTROL_REPLICATED_UPDATE_OID, criticality=0),
     ] + self.serverctrls_for_add_and_modify
     self.lo.modify_ext_s(dn, [(ldap.MOD_REPLACE, key, value)],
                          serverctrls=ctrls)
Exemple #2
0
 def __init__(self,
              criticality=True,
              flags=0,
              maxattributecount=-1,
              cookie=None):
     LDAPControl.__init__(self, DirSyncCtrl.controlType, criticality)
     self.flags = flags
     self.maxattributecount = maxattributecount
     self.cookie = cookie
     self.controlValue = None
Exemple #3
0
    def connect(self, no_starttls=False):
        self.ldapdeleteControl = LDAPControl('1.2.840.113556.1.4.417',
                                             criticality=1)

        self.serverctrls_for_add_and_modify = []
        if 'univention_samaccountname_ldap_check' in baseConfig.get(
                'samba4/ldb/sam/module/prepend', '').split():
            ## The S4 connector must bypass this LDB module if it is activated via samba4/ldb/sam/module/prepend
            ## The OID of the 'bypass_samaccountname_ldap_check' control is defined in ldb.h
            ldb_ctrl_bypass_samaccountname_ldap_check = LDAPControl(
                '1.3.6.1.4.1.10176.1004.0.4.1', criticality=0)
            self.serverctrls_for_add_and_modify.append(
                ldb_ctrl_bypass_samaccountname_ldap_check)

        self.timeout = 5
        use_starttls = 2
        if no_starttls:
            use_starttls = 0

        if self.pw_file:
            fp = open(self.pw_file, 'r')
            login_pw = fp.readline()
            if login_pw[-1] == '\n':
                login_pw = login_pw[:-1]
            fp.close()

        try:
            tls_mode = 2
            if self.ssl == "no" or use_starttls == 0:
                tls_mode = 0

            if self.protocol == 'ldapi':
                import urllib
                socket = urllib.quote(self.socket, '')
                ldapuri = "%s://%s" % (self.protocol, socket)
            else:
                ldapuri = "%s://%s:%d" % (self.protocol, self.adldapbase,
                                          int(self.port))

            # lo=univention.uldap.access(host=self.host, port=int(self.port), base=self.adldapbase, binddn=self.login_dn , bindpw=self.pw_file, start_tls=tls_mode, ca_certfile=self.ca_file, decode_ignorelist=['objectSid', 'objectGUID', 'repsFrom', 'replUpToDateVector', 'ipsecData', 'logonHours', 'userCertificate', 'dNSProperty', 'dnsRecord', 'member'], uri=ldapuri)
            self.lo = ldap.initialize(ldapuri)
            if tls_mode > 0:
                self.lo.start_tls_s()
            self.lo.set_option(ldap.OPT_REFERRALS, 0)

        except:
            ex = 'LDAP Connection to "%s:%s" as "%s" with password "%s" failed (TLS: %s)\n' % (
                self.host, self.port, self.login_dn, login_pw, not no_starttls)
            import traceback
            raise Exception(ex + traceback.format_exc())
 def set_attribute_with_provision_ctrl(self, dn, key, value):
     LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16'
     ctrls = [LDAPControl(LDB_CONTROL_PROVISION_OID, criticality=0)
              ] + self.serverctrls_for_add_and_modify
     self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)),
                          [(ldap.MOD_REPLACE, key, value)],
                          serverctrls=ctrls)
Exemple #5
0
    def connect(self, no_starttls=False):
        self.ldapdeleteControl = LDAPControl('1.2.840.113556.1.4.417',
                                             criticality=1)
        self.timeout = 5
        use_starttls = 2
        if no_starttls:
            use_starttls = 0

        fp = open(self.pw_file, 'r')
        login_pw = fp.readline()
        if login_pw[-1] == '\n':
            login_pw = login_pw[:-1]
        fp.close()

        try:
            self.lo = ldap.initialize(uri="ldap://%s:%s" %
                                      (self.host, self.port))
            if self.ca_file:
                ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_file)
            if use_starttls:
                self.lo.start_tls_s()
            self.lo.simple_bind_s(self.login_dn, login_pw)

        except:
            ex = 'LDAP Connection to "%s:%s" as "%s" with password "%s" failed (TLS: %s, Certificate: %s)\n' % (
                self.host, self.port, self.login_dn, login_pw, not no_starttls,
                self.ca_file)
            import traceback
            raise Exception(ex + traceback.format_exc())

        self.lo.set_option(ldap.OPT_REFERRALS, 0)
Exemple #6
0
def sid_to_s4(s4connector, key, object):
    ud.debug(ud.LDAP, ud.INFO, "sid_to_s4 object: %s" % object)

    sidAttribute = 'sambaSID'
    if s4connector.configRegistry.is_false('connector/s4/mapping/sid', False):
        ud.debug(
            ud.LDAP, ud.INFO,
            'sid_to_s4: SID mapping is disabled via UCR: connector/s4/mapping/sid'
        )
        sidAttribute = 'univentionSamba4SID'
    else:
        # This case will be handled by direct mapping
        return

    # object dn was already mapped to the s4 DN:
    s4_dn = object['dn']
    modlist = []

    # search the ucs object via
    if not object['attributes'].has_key(sidAttribute):
        ud.debug(ud.LDAP, ud.INFO,
                 'sid_to_s4: UCS object does not have a %s' % sidAttribute)
        return

    sambaSID = object['attributes'][sidAttribute]
    # get the ad sid
    (s4_dn,
     s4_attributes) = s4connector.lo_s4.lo.search_s(s4_dn, ldap.SCOPE_BASE,
                                                    '(objectSid=*)',
                                                    ['objectSid'])[0]
    objectSid = s4_attributes.get('objectSid')
    if objectSid:
        # decoded_s4_sid = univention.s4connector.s4.decode_sid(objectSid[0])
        s4_objectSid = ndr_unpack(security.dom_sid, objectSid[0])
        decoded_s4_sid = str(s4_objectSid)
        if decoded_s4_sid == sambaSID[0]:
            ud.debug(ud.LDAP, ud.INFO,
                     'sid_to_s4: objectSid and %s are equal' % sidAttribute)
            return

        ### change objectSID
        #	http://serverfault.com/questions/53717/how-can-i-change-the-sid-of-a-user-account-in-the-active-directory
        #	http://technet.microsoft.com/en-us/library/cc961998.aspx

        ud.debug(
            ud.LDAP, ud.INFO, 'sid_to_s4: changing objectSid from %s to %s' %
            (decoded_s4_sid, sambaSID[0]))
        new_objectSid_ndr = ndr_pack(security.dom_sid(sambaSID[0]))
        modlist.append((ldap.MOD_REPLACE, 'objectSid', new_objectSid_ndr))

        # objectSid modification for an Samba4 object is only possible with the "provision" control:
        LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16'
        controls = [LDAPControl(LDB_CONTROL_PROVISION_OID, criticality=0)]
        s4connector.lo_s4.lo.modify_ext_s(s4_dn, modlist, serverctrls=controls)

    pass
    def connect(self, no_starttls=False):
        self.ldapdeleteControl = LDAPControl('1.2.840.113556.1.4.417',
                                             criticality=1)
        self.timeout = 5
        use_starttls = 2
        if no_starttls:
            use_starttls = 0

        fp = open(self.pw_file, 'r')
        login_pw = fp.readline()
        if login_pw[-1] == '\n':
            login_pw = login_pw[:-1]
        fp.close()

        try:
            self.lo = ldap.initialize(uri="ldap://%s:%s" %
                                      (self.host, self.port))
            if self.ca_file:
                ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_file)
            if use_starttls:
                self.lo.start_tls_s()
        except Exception:
            ex = 'LDAP Connection to "%s:%s" failed (TLS: %s, Certificate: %s)\n' % (
                self.host, self.port, not no_starttls, self.ca_file)
            import traceback
            raise Exception(ex + traceback.format_exc())

        try:
            if self.kerberos:
                os.environ['KRB5CCNAME'] = '/tmp/ucs-test-ldap-glue.cc'
                self.get_kerberos_ticket()
                auth = ldap.sasl.gssapi("")
                self.lo.sasl_interactive_bind_s("", auth)
            else:
                self.lo.simple_bind_s(self.login_dn, login_pw)
        except Exception:
            if self.kerberos:
                cred_msg = '"%s" with Kerberos password "%s"' (self.principal,
                                                               login_pw)
            else:
                cred_msg = '"%s" with simplebind password "%s"' % (
                    self.login_dn, login_pw)
            ex = 'LDAP Bind as %s failed over connection to "%s:%s" (TLS: %s, Certificate: %s)\n' % (
                self.login_dn, cred_msg, self.host, self.port, not no_starttls,
                self.ca_file)
            import traceback
            raise Exception(ex + traceback.format_exc())

        self.lo.set_option(ldap.OPT_REFERRALS, 0)
Exemple #8
0
    def __get_server_controls(self):
        """Create the proxy user server control. The control has the form
        0x04 = Octet String
        4|0x80 sets the length of the string length field at 4 bytes
        the struct() gets us the length in bytes of string self.proxydn
        self.proxydn is the proxy dn to send"""

        if self.proxydn is not None:
            proxydn = chr(0x04) + chr(4|0x80) + struct.pack('l', socket.htonl(len(self.proxydn))) + self.proxydn;

            # Create the proxy control
            sctrl=[]
            sctrl.append(LDAPControl('2.16.840.1.113730.3.4.18',True,proxydn))
        else:
            sctrl=None

        return sctrl
Exemple #9
0
    def connect(self, no_starttls=False):
        self.ldapdeleteControl = LDAPControl('1.2.840.113556.1.4.417',
                                             criticality=1)
        self.timeout = 5
        use_starttls = 2
        if no_starttls:
            use_starttls = 0

        if self.pw_file:
            fp = open(self.pw_file, 'r')
            login_pw = fp.readline()
            if login_pw[-1] == '\n':
                login_pw = login_pw[:-1]
            fp.close()

        try:
            tls_mode = 2
            if self.ssl == "no" or use_starttls == 0:
                tls_mode = 0

            if self.protocol == 'ldapi':
                import urllib
                socket = urllib.quote(self.socket, '')
                ldapuri = "%s://%s" % (self.protocol, socket)
            else:
                ldapuri = "%s://%s:%d" % (self.protocol, self.adldapbase,
                                          int(self.port))

            # lo=univention.uldap.access(host=self.host, port=int(self.port), base=self.adldapbase, binddn=self.login_dn , bindpw=self.pw_file, start_tls=tls_mode, ca_certfile=self.ca_file, decode_ignorelist=['objectSid', 'objectGUID', 'repsFrom', 'replUpToDateVector', 'ipsecData', 'logonHours', 'userCertificate', 'dNSProperty', 'dnsRecord', 'member'], uri=ldapuri)
            self.lo = ldap.initialize(ldapuri)
            if tls_mode > 0:
                self.lo.start_tls_s()
            self.lo.set_option(ldap.OPT_REFERRALS, 0)

        except:
            ex = 'LDAP Connection to "%s:%s" as "%s" with password "%s" failed (TLS: %s)\n' % (
                self.host, self.port, self.login_dn, login_pw, not no_starttls)
            import traceback
            raise Exception(ex + traceback.format_exc())
 def __init__(self,
              criticality,
              controlValue=None,
              encodedControlValue=None):
     LDAPControl.__init__(self, self.controlType, criticality, controlValue,
                          encodedControlValue)
Exemple #11
0
 def __init__(self, criticality, authzId=None):
     LDAPControl.__init__(self, '1.3.6.1.4.1.42.2.27.9.5.2', criticality, authzId)
Exemple #12
0
 def __init__(self, derefspeclist, criticality=True):
     LDAPControl.__init__(self, DerefCtrl.controlType, criticality, derefspeclist)
Exemple #13
0
 def __init__(self,criticality=True,flags=0,maxattributecount=-1,cookie=None):
     LDAPControl.__init__(self,DirSyncCtrl.controlType,criticality)
     self.flags = flags
     self.maxattributecount = maxattributecount
     self.cookie = cookie
     self.controlValue = None
Exemple #14
0
 def __init__(self, criticality=True):
     LDAPControl.__init__(self, TestCtrl.controlType, criticality)
Exemple #15
0
 def __init__(self,criticality=False,derefSpecs=None):
   LDAPControl.__init__(self,self.controlType,criticality)
   self.derefSpecs = derefSpecs or {}
Exemple #16
0
 def __init__(self, criticality, authzId=None):
     LDAPControl.__init__(self, '1.3.6.1.4.1.42.2.27.9.5.2',
                          criticality, authzId)
Exemple #17
0
USER_FILTER = "(&(objectClass=person)(primaryGroupID=7235))"
USER_BASE = "ou=Special Peeps,ou=My Users,dc=host,dc=com"
PAGE_SIZE = 10

# LDAP connection
try:
    ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, 0)
    ldap_connection = ldap.initialize(LDAP_SERVER)
    ldap_connection.simple_bind_s(BIND_DN, BIND_PASS)
except ldap.LDAPError as e:
    sys.stderr.write('Error connecting to LDAP server: ' + str(e) + '\n')
    sys.exit(1)

# Lookup usernames from LDAP via paged search

control = LDAPControl()
paged_results_control = SimplePagedResultsControl(
    ldap.LDAP, True, (PAGE_SIZE, ''))
accounts = []
pages = 0
while True:
    serverctrls = [paged_results_control]
    try:
        msgid = ldap_connection.search_ext(USER_BASE,
                                           ldap.SCOPE_ONELEVEL,
                                           USER_FILTER,
                                           attrlist=['employeeID',
                                                     'sAMAccountName'],
                                           serverctrls=serverctrls)
    except ldap.LDAPError as e:
        sys.stderr.write('Error performing user paged search: ' +
Exemple #18
0
print(60 * '#')

pprint.pprint(l.get_option(ldap.OPT_SERVER_CONTROLS))
l.manage_dsa_it(1, 1)
pprint.pprint(l.get_option(ldap.OPT_SERVER_CONTROLS))
print(60 * '#')

# Search with ManageDsaIT control (which has no value)
pprint.pprint(
    l.search_ext_s(
        'cn=Test-Referral,ou=Testing,dc=stroeder,dc=de',
        ldap.SCOPE_BASE,
        '(objectClass=*)',
        ['*', '+'],
        serverctrls=[LDAPControl('2.16.840.1.113730.3.4.2', 1, None)],
    ))
print(60 * '#')

# Search with Subentries control (which has boolean value)
pprint.pprint(
    l.search_ext_s(
        'dc=stroeder,dc=de',
        ldap.SCOPE_SUBTREE,
        '(objectClass=subentry)',
        ['*', '+'],
        serverctrls=[BooleanControl('1.3.6.1.4.1.4203.1.10.1', 1, 1)],
    ))

print(60 * '#')
Exemple #19
0
 def __init__(self,criticality=True):
     LDAPControl.__init__(self,TestCtrl.controlType,criticality)
Exemple #20
0
 def __init__(self, criticality=True, deref=None):
     LDAPControl.__init__(self, CONTROL_DEREF, criticality)
     self.deref = deref
def password_sync_ucs_to_s4(s4connector, key, object):
	_d = ud.function('ldap.s4.password_sync_ucs_to_s4')
	ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4 called")

	modify = False
	old_ucs_object = object.get('old_ucs_object', {})
	new_ucs_object = object.get('new_ucs_object', {})
	if old_ucs_object or new_ucs_object:
		for attr in ['sambaLMPassword', 'sambaNTPassword', 'sambaPwdLastSet', 'sambaPwdMustChange', 'krb5PrincipalName', 'krb5Key', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService']:
			old_values = set(old_ucs_object.get(attr, []))
			new_values = set(new_ucs_object.get(attr, []))
			if old_values != new_values:
				modify = True
				break
	else:
		# add mode
		modify = True

	if not modify:
		ud.debug(ud.LDAP, ud.INFO, 'password_sync_ucs_to_s4: the password for %s has not been changed. Skipping password sync.' % (object['dn']))
		return

	try:
		ud.debug(ud.LDAP, ud.INFO, "Object DN=%s" % object['dn'])
	except:  # FIXME: which exception is to be caught?
		ud.debug(ud.LDAP, ud.INFO, "Object DN not printable")

	ucs_object = s4connector._object_mapping(key, object, 'con')

	try:
		ud.debug(ud.LDAP, ud.INFO, "   UCS DN = %s" % ucs_object['dn'])
	except:  # FIXME: which exception is to be caught?
		ud.debug(ud.LDAP, ud.INFO, "   UCS DN not printable")

	try:
		ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaLMPassword', 'sambaNTPassword', 'sambaPwdLastSet', 'sambaPwdMustChange', 'krb5PrincipalName', 'krb5Key', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService'], required=True)
	except ldap.NO_SUCH_OBJECT:
		ud.debug(ud.LDAP, ud.PROCESS, "password_sync_ucs_to_s4: The UCS object (%s) was not found. The object was removed." % ucs_object['dn'])
		return

	services = ucs_object_attributes.get('univentionService', [])
	if 'Samba 4' in services:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: %s is a S4 server, skip password sync" % ucs_object['dn'])
		return

	sambaPwdLastSet = None
	if 'sambaPwdLastSet' in ucs_object_attributes:
		sambaPwdLastSet = long(ucs_object_attributes['sambaPwdLastSet'][0])
	ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaPwdLastSet: %s" % sambaPwdLastSet)

	if 'sambaPwdMustChange' in ucs_object_attributes:
		sambaPwdMustChange = long(ucs_object_attributes['sambaPwdMustChange'][0])
		ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_to_s4: Ignoring sambaPwdMustChange: %s" % sambaPwdMustChange)

	ucsLMhash = ucs_object_attributes.get('sambaLMPassword', [None])[0]
	ucsNThash = ucs_object_attributes.get('sambaNTPassword', [None])[0]
	krb5Principal = ucs_object_attributes.get('krb5PrincipalName', [None])[0]
	krb5Key = ucs_object_attributes.get('krb5Key', [])

	if not ucsNThash:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaNTPassword missing in UCS LDAP, trying krb5Key")
		ucsNThash = extract_NThash_from_krb5key(krb5Key)

	if not ucsNThash:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get NT Password-Hash from UCS LDAP")

	# ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from UCS: %s" % ucsNThash)

	s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['pwdLastSet', 'objectSid'])
	pwdLastSet = None
	if 'pwdLastSet' in s4_object_attributes:
		pwdLastSet = long(s4_object_attributes['pwdLastSet'][0])
	objectSid = univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0])
	ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet from S4 : %s" % pwdLastSet)
	# rid = None
	# if s4_object_attributes.has_key('objectSid'):
	# 	rid = str(univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]).split('-')[-1])

	pwd_set = False
	filter_expr = format_escaped('(objectSid={0!e})', objectSid)
	res = s4connector.lo_s4.search(filter=filter_expr, attr=['unicodePwd', 'userPrincipalName', 'supplementalCredentials', 'msDS-KeyVersionNumber', 'dBCSPwd'])
	s4_search_attributes = res[0][1]

	unicodePwd_attr = s4_search_attributes.get('unicodePwd', [None])[0]
	dBCSPwd_attr = s4_search_attributes.get('dBCSPwd', [None])[0]
	userPrincipalName_attr = s4_search_attributes.get('userPrincipalName', [None])[0]
	supplementalCredentials = s4_search_attributes.get('supplementalCredentials', [None])[0]
	msDS_KeyVersionNumber = s4_search_attributes.get('msDS-KeyVersionNumber', [0])[0]
	# ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from S4: %s" % unicodePwd_attr)

	s4NThash = None
	if unicodePwd_attr:
		s4NThash = binascii.b2a_hex(unicodePwd_attr).upper()
	else:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get NT Password-Hash from S4")

	s4LMhash = None
	if dBCSPwd_attr:
		s4LMhash = binascii.b2a_hex(dBCSPwd_attr).upper()
	else:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get LM Password-Hash from S4")

	modlist = []
	if krb5Principal != userPrincipalName_attr:
		if krb5Principal:
			if not userPrincipalName_attr:  # new and not old
				modlist.append((ldap.MOD_ADD, 'userPrincipalName', krb5Principal))
			else:  # new and old differ
				if krb5Principal.lower() != userPrincipalName_attr.lower():
					ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_to_s4: userPrincipalName != krb5Principal: '%s' != '%s'" % (userPrincipalName_attr, krb5Principal))
				modlist.append((ldap.MOD_REPLACE, 'userPrincipalName', krb5Principal))
		else:
			if userPrincipalName_attr:  # old and not new
				modlist.append((ldap.MOD_DELETE, 'userPrincipalName', userPrincipalName_attr))

	if not ucsNThash == s4NThash:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: NT Hash S4: %s NT Hash UCS: %s" % (s4NThash, ucsNThash))
		# Now if ucsNThash is empty there should at least some timestamp in UCS,
		# otherwise it's probably not a good idea to remove the unicodePwd.
		# Usecase: LDB module on ucs_3.0-0-ucsschool slaves creates XP computers/windows in UDM without password
		if ucsNThash or sambaPwdLastSet:
			pwd_set = True
			unicodePwd_new = None
			if ucsNThash:
				try:
					unicodePwd_new = binascii.a2b_hex(ucsNThash)
				except TypeError as exc:
					if ucsNThash.startswith("NO PASSWORD"):
						pwd_set = False
					else:
						raise
			if pwd_set:
				if unicodePwd_attr:
					modlist.append((ldap.MOD_DELETE, 'unicodePwd', unicodePwd_attr))
				if unicodePwd_new:
					modlist.append((ldap.MOD_ADD, 'unicodePwd', unicodePwd_new))

	if not ucsLMhash == s4LMhash:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: LM Hash S4: %s LM Hash UCS: %s" % (s4LMhash, ucsLMhash))
		pwd_set = True
		if dBCSPwd_attr:
			modlist.append((ldap.MOD_DELETE, 'dBCSPwd', dBCSPwd_attr))
		if ucsLMhash:
			dBCSPwd_new = binascii.a2b_hex(ucsLMhash)
			modlist.append((ldap.MOD_ADD, 'dBCSPwd', dBCSPwd_new))

	if pwd_set or not supplementalCredentials:
		if krb5Principal:
			# encoding of Samba4 supplementalCredentials
			if supplementalCredentials:
				modlist.append((ldap.MOD_DELETE, 'supplementalCredentials', supplementalCredentials))
			if krb5Key:
				supplementalCredentials_new = calculate_supplementalCredentials(krb5Key, supplementalCredentials)
				if supplementalCredentials_new:
					modlist.append((ldap.MOD_ADD, 'supplementalCredentials', supplementalCredentials_new))
				else:
					ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: no supplementalCredentials_new")
				# if supplementalCredentials:
				#	modlist.append((ldap.MOD_REPLACE, 'msDS-KeyVersionNumber', krb5KeyVersionNumber))
				# else:
				#	modlist.append((ldap.MOD_ADD, 'msDS-KeyVersionNumber', krb5KeyVersionNumber))

		if sambaPwdLastSet is None:
			sambaPwdLastSet = int(time.time())
			newpwdlastset = str(univention.s4connector.s4.samba2s4_time(sambaPwdLastSet))
		elif sambaPwdLastSet in [0, 1]:
			ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: samba pwd expired, set newpwdLastSet to 0")
			newpwdlastset = 0
		else:
			newpwdlastset = univention.s4connector.s4.samba2s4_time(sambaPwdLastSet)
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet in modlist: %s" % newpwdlastset)
		modlist.append((ldap.MOD_REPLACE, 'pwdLastSet', str(newpwdlastset)))
		modlist.append((ldap.MOD_REPLACE, 'badPwdCount', '0'))
		modlist.append((ldap.MOD_REPLACE, 'badPasswordTime', '0'))
		modlist.append((ldap.MOD_REPLACE, 'lockoutTime', '0'))

	else:
		ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: No password change to sync to S4 ")

		# check pwdLastSet
		if sambaPwdLastSet is not None:
			if sambaPwdLastSet in [0, 1]:
				newpwdlastset = 0
			else:
				newpwdlastset = univention.s4connector.s4.samba2s4_time(sambaPwdLastSet)
			ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaPwdLastSet: %d" % sambaPwdLastSet)
			ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: newpwdlastset  : %s" % newpwdlastset)
			ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet (AD): %s" % pwdLastSet)
			if newpwdlastset != pwdLastSet and abs(newpwdlastset - pwdLastSet) >= 10000000:
				modlist.append((ldap.MOD_REPLACE, 'pwdLastSet', str(newpwdlastset)))

	# TODO: Password History
	ctrl_bypass_password_hash = LDAPControl('1.3.6.1.4.1.7165.4.3.12', criticality=0)
	ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: modlist: %s" % modlist)
	if modlist:
		s4connector.lo_s4.lo.modify_ext_s(compatible_modstring(object['dn']), modlist, serverctrls=[ctrl_bypass_password_hash])
Exemple #22
0
 def __init__(self, criticality=True, deref=None):
     LDAPControl.__init__(self, CONTROL_DEREF, criticality)
     self.deref = deref
Exemple #23
0
 def __init__(self, criticality=False, derefSpecs=None):
     LDAPControl.__init__(self, self.controlType, criticality)
     self.derefSpecs = derefSpecs or {}
Exemple #24
0
 def __init__(self, criticality, controlValue=None, encodedControlValue=None):
     LDAPControl.__init__(self, self.controlType, criticality, controlValue, encodedControlValue)
Exemple #25
0
 def __init__(self, derefspeclist, criticality=True):
     LDAPControl.__init__(self, DerefCtrl.controlType, criticality,
                          derefspeclist)
Exemple #26
0
def password_sync_ucs_to_s4(s4connector, key, object):
    _d = ud.function('ldap.s4.password_sync_ucs_to_s4')
    ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4 called")

    compatible_modstring = univention.s4connector.s4.compatible_modstring
    try:
        ud.debug(ud.LDAP, ud.INFO, "Object DN=%s" % object['dn'])
    except:  # FIXME: which exception is to be caught?
        ud.debug(ud.LDAP, ud.INFO, "Object DN not printable")

    ucs_object = s4connector._object_mapping(key, object, 'con')

    try:
        ud.debug(ud.LDAP, ud.INFO, "   UCS DN = %s" % ucs_object['dn'])
    except:  # FIXME: which exception is to be caught?
        ud.debug(ud.LDAP, ud.INFO, "   UCS DN not printable")

    try:
        res = s4connector.lo.lo.search(
            base=ucs_object['dn'],
            scope='base',
            attr=[
                'sambaLMPassword', 'sambaNTPassword', 'sambaPwdLastSet',
                'sambaPwdMustChange', 'krb5PrincipalName', 'krb5Key',
                'shadowLastChange', 'shadowMax', 'krb5PasswordEnd',
                'univentionService'
            ])
    except ldap.NO_SUCH_OBJECT:
        ud.debug(
            ud.LDAP, ud.PROCESS,
            "password_sync_ucs_to_s4: The UCS object (%s) was not found. The object was removed."
            % ucs_object['dn'])
        return

    services = res[0][1].get('univentionService', [])
    if 'Samba 4' in services:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: %s is a S4 server, skip password sync" %
            ucs_object['dn'])
        return

    sambaPwdLastSet = None
    if res[0][1].has_key('sambaPwdLastSet'):
        sambaPwdLastSet = long(res[0][1]['sambaPwdLastSet'][0])
    ud.debug(ud.LDAP, ud.INFO,
             "password_sync_ucs_to_s4: sambaPwdLastSet: %s" % sambaPwdLastSet)

    sambaPwdMustChange = -1
    if res[0][1].has_key('sambaPwdMustChange'):
        sambaPwdMustChange = long(res[0][1]['sambaPwdMustChange'][0])
    ud.debug(
        ud.LDAP, ud.INFO,
        "password_sync_ucs_to_s4: sambaPwdMustChange: %s" % sambaPwdMustChange)

    ucsLMhash = res[0][1].get('sambaLMPassword', [None])[0]
    ucsNThash = res[0][1].get('sambaNTPassword', [None])[0]
    krb5Principal = res[0][1].get('krb5PrincipalName', [None])[0]
    krb5Key = res[0][1].get('krb5Key', [])

    if not ucsNThash:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: sambaNTPassword missing in UCS LDAP, trying krb5Key"
        )
        ucsNThash = extract_NThash_from_krb5key(krb5Key)

    if not ucsNThash:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: Failed to get NT Password-Hash from UCS LDAP"
        )

    # ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from UCS: %s" % ucsNThash)

    res = s4connector.lo_s4.lo.search_s(
        univention.s4connector.s4.compatible_modstring(object['dn']),
        ldap.SCOPE_BASE, '(objectClass=*)', ['pwdLastSet', 'objectSid'])
    pwdLastSet = None
    if res[0][1].has_key('pwdLastSet'):
        pwdLastSet = long(res[0][1]['pwdLastSet'][0])
    objectSid = univention.s4connector.s4.decode_sid(res[0][1]['objectSid'][0])
    ud.debug(ud.LDAP, ud.INFO,
             "password_sync_ucs_to_s4: pwdLastSet from S4 : %s" % pwdLastSet)
    # rid = None
    # if res[0][1].has_key('objectSid'):
    # 	rid = str(univention.s4connector.s4.decode_sid(res[0][1]['objectSid'][0]).split('-')[-1])

    pwd_set = False
    res = s4connector.lo_s4.lo.search_s(
        s4connector.lo_s4.base, ldap.SCOPE_SUBTREE,
        compatible_modstring('(objectSid=%s)' % objectSid), [
            'unicodePwd', 'userPrincipalName', 'supplementalCredentials',
            'msDS-KeyVersionNumber', 'dBCSPwd'
        ])
    unicodePwd_attr = res[0][1].get('unicodePwd', [None])[0]
    dBCSPwd_attr = res[0][1].get('dBCSPwd', [None])[0]
    userPrincipalName_attr = res[0][1].get('userPrincipalName', [None])[0]
    supplementalCredentials = res[0][1].get('supplementalCredentials',
                                            [None])[0]
    msDS_KeyVersionNumber = res[0][1].get('msDS-KeyVersionNumber', [0])[0]
    # ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from S4: %s" % unicodePwd_attr)

    s4NThash = None
    if unicodePwd_attr:
        s4NThash = binascii.b2a_hex(unicodePwd_attr).upper()
    else:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: Failed to get NT Password-Hash from S4")

    s4LMhash = None
    if dBCSPwd_attr:
        s4LMhash = binascii.b2a_hex(dBCSPwd_attr).upper()
    else:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: Failed to get LM Password-Hash from S4")

    modlist = []
    if krb5Principal != userPrincipalName_attr:
        if krb5Principal:
            if not userPrincipalName_attr:  ## new and not old
                modlist.append(
                    (ldap.MOD_ADD, 'userPrincipalName', krb5Principal))
            else:  ## new and old differ
                if krb5Principal.lower() != userPrincipalName_attr.lower():
                    ud.debug(
                        ud.LDAP, ud.WARN,
                        "password_sync_ucs_to_s4: userPrincipalName != krb5Principal: '%s' != '%s'"
                        % (userPrincipalName_attr, krb5Principal))
                modlist.append(
                    (ldap.MOD_REPLACE, 'userPrincipalName', krb5Principal))
        else:
            if userPrincipalName_attr:  ## old and not new
                modlist.append((ldap.MOD_DELETE, 'userPrincipalName',
                                userPrincipalName_attr))

    if not ucsNThash == s4NThash:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: NT Hash S4: %s NT Hash UCS: %s" %
            (s4NThash, ucsNThash))
        ## Now if ucsNThash is empty there should at least some timestamp in UCS,
        ## otherwise it's probably not a good idea to remove the unicodePwd.
        ## Usecase: LDB module on ucs_3.0-0-ucsschool slaves creates XP computers/windows in UDM without password
        if ucsNThash or sambaPwdLastSet:
            pwd_set = True
            if unicodePwd_attr:
                modlist.append(
                    (ldap.MOD_DELETE, 'unicodePwd', unicodePwd_attr))
            if ucsNThash:
                unicodePwd_new = binascii.a2b_hex(ucsNThash)
                modlist.append((ldap.MOD_ADD, 'unicodePwd', unicodePwd_new))

    if not ucsLMhash == s4LMhash:
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: LM Hash S4: %s LM Hash UCS: %s" %
            (s4LMhash, ucsLMhash))
        pwd_set = True
        if dBCSPwd_attr:
            modlist.append((ldap.MOD_DELETE, 'dBCSPwd', dBCSPwd_attr))
        if ucsLMhash:
            dBCSPwd_new = binascii.a2b_hex(ucsLMhash)
            modlist.append((ldap.MOD_ADD, 'dBCSPwd', dBCSPwd_new))

    if pwd_set or not supplementalCredentials:
        if krb5Principal:
            ## encoding of Samba4 supplementalCredentials
            if supplementalCredentials:
                modlist.append((ldap.MOD_DELETE, 'supplementalCredentials',
                                supplementalCredentials))
            if krb5Key:
                supplementalCredentials_new = calculate_supplementalCredentials(
                    krb5Key, supplementalCredentials)
                if supplementalCredentials_new:
                    modlist.append((ldap.MOD_ADD, 'supplementalCredentials',
                                    supplementalCredentials_new))
                else:
                    ud.debug(
                        ud.LDAP, ud.INFO,
                        "password_sync_ucs_to_s4: no supplementalCredentials_new"
                    )
                #if supplementalCredentials:
                #	modlist.append((ldap.MOD_REPLACE, 'msDS-KeyVersionNumber', krb5KeyVersionNumber))
                #else:
                #	modlist.append((ldap.MOD_ADD, 'msDS-KeyVersionNumber', krb5KeyVersionNumber))

        if sambaPwdMustChange >= 0 and sambaPwdMustChange < time.time():
            # password expired, must be changed on next login
            ud.debug(
                ud.LDAP, ud.INFO,
                "password_sync_ucs_to_s4: samba pwd expired, set newpwdLastSet to 0"
            )
            newpwdlastset = "0"
        else:
            if sambaPwdLastSet == None:
                sambaPwdLastSet = int(time.time())
                newpwdlastset = str(
                    univention.s4connector.s4.samba2s4_time(sambaPwdLastSet))
            elif sambaPwdLastSet in [0, 1]:
                newpwdlastset = "0"
            else:
                newpwdlastset = str(
                    univention.s4connector.s4.samba2s4_time(sambaPwdLastSet))
        ud.debug(
            ud.LDAP, ud.INFO,
            "password_sync_ucs_to_s4: pwdlastset in modlist: %s" %
            newpwdlastset)
        modlist.append((ldap.MOD_REPLACE, 'pwdlastset', newpwdlastset))

    else:
        ud.debug(ud.LDAP, ud.INFO,
                 "password_sync_ucs_to_s4: No password change to sync to S4 ")

        # check pwdLastSet
        if sambaPwdLastSet != None:
            newpwdlastset = str(
                univention.s4connector.s4.samba2s4_time(sambaPwdLastSet))
            ud.debug(
                ud.LDAP, ud.INFO,
                "password_sync_ucs_to_s4: sambaPwdLastSet: %d" %
                sambaPwdLastSet)
            ud.debug(
                ud.LDAP, ud.INFO,
                "password_sync_ucs_to_s4: newpwdlastset  : %s" % newpwdlastset)
            ud.debug(
                ud.LDAP, ud.INFO,
                "password_sync_ucs_to_s4: pwdLastSet (AD): %s" % pwdLastSet)
            if sambaPwdLastSet in [0, 1]:
                modlist.append((ldap.MOD_REPLACE, 'pwdlastset', "0"))
            elif pwdLastSet != newpwdlastset:
                modlist.append((ldap.MOD_REPLACE, 'pwdlastset', newpwdlastset))

    ## TODO: Password History
    ctrl_bypass_password_hash = LDAPControl('1.3.6.1.4.1.7165.4.3.12',
                                            criticality=0)
    ud.debug(ud.LDAP, ud.INFO,
             "password_sync_ucs_to_s4: modlist: %s" % modlist)
    if modlist:
        s4connector.lo_s4.lo.modify_ext_s(
            compatible_modstring(object['dn']),
            modlist,
            serverctrls=[ctrl_bypass_password_hash])