Example #1
0
	def move(self, dn, newdn):
		newrdn = get_rdn (newdn)
		parent1 = get_parent_dn (dn)
		parent2 = get_parent_dn (newdn)
		
		if parent1 != parent2:
			self.lo.rename_s(s4.compatible_modstring (unicode (dn)),
							 s4.compatible_modstring (unicode (newrdn)),
							 s4.compatible_modstring (unicode (parent2)))
		else:
			self.lo.modrdn_s(s4.compatible_modstring (unicode (dn)),
							 s4.compatible_modstring (unicode (newrdn)))
Example #2
0
    def move(self, dn, newdn):
        newrdn = get_rdn(newdn)
        parent1 = get_parent_dn(dn)
        parent2 = get_parent_dn(newdn)

        if parent1 != parent2:
            self.lo.rename_s(s4.compatible_modstring(unicode(dn)),
                             s4.compatible_modstring(unicode(newrdn)),
                             s4.compatible_modstring(unicode(parent2)))
        else:
            self.lo.modrdn_s(s4.compatible_modstring(unicode(dn)),
                             s4.compatible_modstring(unicode(newrdn)))
Example #3
0
 def set_attributes(self, dn, **attributes):
     old_attributes = self.get(dn, attr=attributes.keys())
     ldif = modlist.modifyModlist(old_attributes, attributes)
     comp_dn = s4.compatible_modstring(unicode(dn))
     self.lo.modify_ext_s(comp_dn,
                          ldif,
                          serverctrls=self.serverctrls_for_add_and_modify)
 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)
Example #5
0
 def create(self, dn, attrs):
     attrs = dict(
         (name, [attr] if not isinstance(attr, (list, tuple)) else attr)
         for name, attr in attrs.items())
     ldif = modlist.addModlist(attrs)
     self.lo.add_ext_s(s4.compatible_modstring(unicode(dn)),
                       ldif,
                       serverctrls=self.serverctrls_for_add_and_modify)
Example #6
0
 def set_attributes(self, dn, **attributes):
     old_attributes = self.get(dn, attr=attributes.keys())
     attributes = dict(
         (name, [attr] if not isinstance(attr, (list, tuple)) else attr)
         for name, attr in attributes.items())
     ldif = modlist.modifyModlist(old_attributes, attributes)
     comp_dn = s4.compatible_modstring(unicode(dn))
     if ldif:
         self.lo.modify_ext_s(
             comp_dn, ldif, serverctrls=self.serverctrls_for_add_and_modify)
Example #7
0
 def append_to_attribute(self, dn, key, value):
     self.lo.modify_s(
         s4.compatible_modstring(unicode(dn)),
         [(ldap.MOD_ADD, key, s4.compatible_modstring(unicode(value)))])
Example #8
0
 def delete_attribute(self, dn, key):
     self.lo.modify_s(s4.compatible_modstring(unicode(dn)),
                      [(ldap.MOD_DELETE, key, None)])
Example #9
0
	def delete_attribute(self, dn, key):
		self.lo.modify_s (s4.compatible_modstring (unicode (dn)),
						  [(ldap.MOD_DELETE, key, None)])
Example #10
0
 def append_to_attribute(self, dn, key, value):
     self.lo.modify_ext_s(
         s4.compatible_modstring(unicode(dn)),
         [(ldap.MOD_ADD, key, s4.compatible_modstring(unicode(value)))],
         serverctrls=self.serverctrls_for_add_and_modify)
Example #11
0
 def create(self, dn, attrs):
     ldif = modlist.addModlist(attrs)
     self.lo.add_ext_s(s4.compatible_modstring(unicode(dn)),
                       ldif,
                       serverctrls=self.serverctrls_for_add_and_modify)
Example #12
0
	def delete(self, dn):
		self.lo.delete_s(s4.compatible_modstring (unicode (dn)))
Example #13
0
	def create(self, dn, attrs):
		ldif = modlist.addModlist(attrs)
		self.lo.add_s(s4.compatible_modstring (unicode (dn)),ldif)
Example #14
0
	def remove_from_attribute(self, dn, key, value):
		self.lo.modify_s (s4.compatible_modstring (unicode (dn)),
						  [(ldap.MOD_DELETE, key, s4.compatible_modstring (unicode (value)))])
Example #15
0
	def append_to_attribute(self, dn, key, value):
		self.lo.modify_s (s4.compatible_modstring (unicode (dn)),
						  [(ldap.MOD_ADD, key, s4.compatible_modstring (unicode (value)))])
Example #16
0
 def remove_from_attribute(self, dn, key, value):
     self.lo.modify_s(
         s4.compatible_modstring(unicode(dn)),
         [(ldap.MOD_DELETE, key, s4.compatible_modstring(unicode(value)))])
Example #17
0
 def create(self, dn, attrs):
     ldif = modlist.addModlist(attrs)
     self.lo.add_s(s4.compatible_modstring(unicode(dn)), ldif)
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])
Example #19
0
 def delete(self, dn):
     self.lo.delete_s(s4.compatible_modstring(unicode(dn)))
def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=True):
	_d = ud.function('ldap.s4.password_sync_s4_to_ucs')
	ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs called")

	if ucs_object['modtype'] == 'modify':
		if 'pwdLastSet' not in ucs_object.get('changed_attributes', []):
			ud.debug(ud.LDAP, ud.INFO, 'password_sync_s4_to_ucs: the password for %s has not been changed. Skipping password sync.' % (ucs_object['dn']))
			return

	object = s4connector._object_mapping(key, ucs_object, 'ucs')
	s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['objectSid', 'pwdLastSet'])

	if s4connector.isInCreationList(object['dn']):
		s4connector.removeFromCreationList(object['dn'])
		ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Synchronisation of password has been canceled. Object was just created.")
		return

	pwdLastSet = None
	if 'pwdLastSet' in s4_object_attributes:
		pwdLastSet = long(s4_object_attributes['pwdLastSet'][0])
	ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: pwdLastSet from S4: %s (%s)" % (pwdLastSet, s4_object_attributes))
	objectSid = univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0])

	# rid = None
	# if s4_object_attributes.has_key('objectSid'):
	# 	rid = str(univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]).split('-')[-1])

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

	unicodePwd_attr = s4_search_attributes.get('unicodePwd', [None])[0]
	if unicodePwd_attr:
		ntPwd = binascii.b2a_hex(unicodePwd_attr).upper()

		lmPwd = ''
		dBCSPwd = s4_search_attributes.get('dBCSPwd', [None])[0]
		if dBCSPwd:
			lmPwd = binascii.b2a_hex(dBCSPwd).upper()

		supplementalCredentials = s4_search_attributes.get('supplementalCredentials', [None])[0]
		msDS_KeyVersionNumber = s4_search_attributes.get('msDS-KeyVersionNumber', [0])[0]

		ntPwd_ucs = ''
		lmPwd_ucs = ''
		krb5Principal = ''
		userPassword = ''
		modlist = []
		ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaPwdMustChange', 'sambaPwdLastSet', 'sambaNTPassword', 'sambaLMPassword', 'krb5PrincipalName', 'krb5Key', 'krb5KeyVersionNumber', 'userPassword', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService'])

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

		if 'sambaNTPassword' in ucs_object_attributes:
			ntPwd_ucs = ucs_object_attributes['sambaNTPassword'][0]
		if 'sambaLMPassword' in ucs_object_attributes:
			lmPwd_ucs = ucs_object_attributes['sambaLMPassword'][0]
		if 'krb5PrincipalName' in ucs_object_attributes:
			krb5Principal = ucs_object_attributes['krb5PrincipalName'][0]
		if 'userPassword' in ucs_object_attributes:
			userPassword = ucs_object_attributes['userPassword'][0]
		sambaPwdLastSet = None
		if 'sambaPwdLastSet' in ucs_object_attributes:
			sambaPwdLastSet = ucs_object_attributes['sambaPwdLastSet'][0]
		ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet: %s" % sambaPwdLastSet)
		sambaPwdMustChange = ''
		if 'sambaPwdMustChange' in ucs_object_attributes:
			sambaPwdMustChange = ucs_object_attributes['sambaPwdMustChange'][0]
			ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Found sambaPwdMustChange: %s" % sambaPwdMustChange)
		krb5Key_ucs = ucs_object_attributes.get('krb5Key', [])
		userPassword_ucs = ucs_object_attributes.get('userPassword', [None])[0]
		krb5KeyVersionNumber = ucs_object_attributes.get('krb5KeyVersionNumber', [None])[0]

		pwd_changed = False
		if ntPwd != ntPwd_ucs:
			pwd_changed = True
			modlist.append(('sambaNTPassword', ntPwd_ucs, str(ntPwd)))

		if lmPwd != lmPwd_ucs:
			pwd_changed = True
			modlist.append(('sambaLMPassword', lmPwd_ucs, str(lmPwd)))

		if pwd_changed:
			if krb5Principal:
				# decoding of Samba4 supplementalCredentials
				krb5Key_new = calculate_krb5key(unicodePwd_attr, supplementalCredentials, int(msDS_KeyVersionNumber))

				modlist.append(('krb5Key', krb5Key_ucs, krb5Key_new))
				if int(msDS_KeyVersionNumber) != int(krb5KeyVersionNumber):
					modlist.append(('krb5KeyVersionNumber', krb5KeyVersionNumber, msDS_KeyVersionNumber))

			# Append modification as well to modlist, to apply in one transaction
			if modifyUserPassword:
				modlist.append(('userPassword', userPassword_ucs, '{K5KEY}'))
		else:
			ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: No password change to sync to UCS")

		try:
			old_pwdLastSet = object['old_s4_object']['pwdLastSet'][0]
		except (KeyError, IndexError):
			old_pwdLastSet = None

		if pwdLastSet != old_pwdLastSet:
			ud.debug(ud.LDAP, ud.ALL, "password_sync_s4_to_ucs: updating shadowLastChange")
			old_shadowLastChange = ucs_object_attributes.get('shadowLastChange', [None])[0]
			new_shadowLastChange = old_shadowLastChange

			# shadowMax (set to value of univentionPWExpiryInterval, otherwise delete)
			# krb5PasswordEnd (set to today + univentionPWExpiryInterval, otherwise delete)
			old_shadowMax = ucs_object_attributes.get('shadowMax', [None])[0]
			new_shadowMax = old_shadowMax
			old_krb5end = ucs_object_attributes.get('krb5PasswordEnd', [None])[0]
			new_krb5end = old_krb5end

			pwdLastSet_unix = univention.s4connector.s4.s42samba_time(pwdLastSet)
			newSambaPwdLastSet = str(pwdLastSet_unix)

			if pwdLastSet == 0:  # pwd change on next login
				new_shadowMax = '1'
				expiry = long(time.time())
				new_krb5end = time.strftime("%Y%m%d000000Z", time.gmtime(expiry))
			else:                # not pwd change on next login
				new_shadowLastChange = str(pwdLastSet_unix / 3600 / 24)
				userobject = s4connector.get_ucs_object('user', ucs_object['dn'])
				if not userobject:
					ud.debug(ud.LDAP, ud.ERROR, "password_sync_s4_to_ucs: couldn't get user-object from UCS")
					return False

				pwhistoryPolicy = userobject.loadPolicyObject('policies/pwhistory')
				try:
					expiryInterval = int(pwhistoryPolicy['expiryInterval'])
				except (TypeError, ValueError):
					# expiryInterval is empty or no legal int-string
					pwhistoryPolicy['expiryInterval'] = ''
					expiryInterval = -1

				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: password expiryInterval for %s is %s" % (ucs_object['dn'], expiryInterval))
				if expiryInterval in (-1, 0):
					new_shadowMax = ''
					new_krb5end = ''
				else:
					new_shadowMax = str(expiryInterval)
					new_krb5end = time.strftime("%Y%m%d000000Z", time.gmtime((pwdLastSet_unix + (int(expiryInterval) * 3600 * 24))))

			if new_shadowLastChange != old_shadowLastChange:
				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update shadowLastChange to %s for %s" % (new_shadowLastChange, ucs_object['dn']))
				modlist.append(('shadowLastChange', old_shadowLastChange, new_shadowLastChange))
			if new_shadowMax != old_shadowMax:
				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update shadowMax to %s for %s" % (new_shadowMax, ucs_object['dn']))
				modlist.append(('shadowMax', old_shadowMax, new_shadowMax))
			if new_krb5end != old_krb5end:
				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update krb5PasswordEnd to %s for %s" % (new_krb5end, ucs_object['dn']))
				modlist.append(('krb5PasswordEnd', old_krb5end, new_krb5end))

			if sambaPwdLastSet:
				if sambaPwdLastSet != newSambaPwdLastSet:
					modlist.append(('sambaPwdLastSet', sambaPwdLastSet, newSambaPwdLastSet))
					ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet in modlist (replace): %s" % newSambaPwdLastSet)
			else:
				modlist.append(('sambaPwdLastSet', '', newSambaPwdLastSet))
				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet in modlist (set): %s" % newSambaPwdLastSet)

			if sambaPwdMustChange:
				modlist.append(('sambaPwdMustChange', sambaPwdMustChange, ''))
				ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Removing sambaPwdMustChange")

		if len(modlist) > 0:
			ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: modlist: %s" % modlist)
			s4connector.lo.lo.modify(ucs_object['dn'], modlist)

	else:
		ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_s4_to_ucs: Failed to get Password-Hash from S4")
Example #21
0
 def set_attribute(self, dn, key, value):
     if key not in s4.DECODE_IGNORELIST:
         value = s4.compatible_modstring(unicode(value))
     self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)),
                          [(ldap.MOD_REPLACE, key, value)],
                          serverctrls=self.serverctrls_for_add_and_modify)
def lockout_sync_ucs_to_s4(s4connector, key, object):
	"""
	Sync unlock *modification* from OpenLDAP to Samba/AD:
		sync OpenLDAP ("L" not in sambaAcctFlags) ->  Samba/AD lockoutTime = 0

		sync OpenLDAP ("L" in sambaAcctFlags) ->  Samba/AD lockoutTime = sambaBadPasswordTime
		and  OpenLDAP sambaBadPasswordTime    ->  Samba/AD badPasswordTime
	"""
	function_name = 'lockout_sync_ucs_to_s4'
	_d = ud.function('ldap.s4.%s' % function_name)
	ud.debug(ud.LDAP, ud.INFO, "%s called" % function_name)

	if object['modtype'] not in ('modify', 'add'):
		return

	new_ucs_object = object.get('new_ucs_object', {})
	if not new_ucs_object:
		# only set by sync_from_ucs in MODIFY case
		return

	old_ucs_object = object.get('old_ucs_object', {})
	if not old_ucs_object:
		# only set by sync_from_ucs in MODIFY case
		return

	new_sambaAcctFlags = new_ucs_object.get('sambaAcctFlags', [''])[0]
	is_locked = "L" in new_sambaAcctFlags

	old_sambaAcctFlags = old_ucs_object.get('sambaAcctFlags', [''])[0]
	was_locked = "L" in old_sambaAcctFlags

	if is_locked == was_locked:
		# Require a change in the pickled state
		return

	modlist = []
	if not is_locked:
		s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['lockoutTime', 'badPasswordTime'])
		if 'lockoutTime' not in s4_object_attributes:
			return

		lockoutTime = s4_object_attributes['lockoutTime'][0]
		if lockoutTime == "0":
			return

		# Now object.get('new_ucs_object') may be a stale pickled state, so let's lookup the current OpenLDAP object state
		# Unfortunately "object" doesn't hold the current OpenLDAP DN, so we need to map back first
		ucs_object = s4connector._object_mapping(key, object)
		try:
			ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaAcctFlags', 'sambaBadPasswordTime'], required=True)
		except ldap.NO_SUCH_OBJECT:
			ud.debug(ud.LDAP, ud.WARN, "%s: The UCS object (%s) was not found. The object was removed." % (function_name, ucs_object['dn']))
			return
		sambaAcctFlags = ucs_object_attributes.get('sambaAcctFlags', [''])[0]

		if "L" in sambaAcctFlags:
			## currently locked again
			return

		sambaBadPasswordTime = ucs_object_attributes.get('sambaBadPasswordTime', [''])[0]
		if sambaBadPasswordTime and sambaBadPasswordTime != "0":
			ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is unlocked, but sambaBadPasswordTime is set." % (function_name, ucs_object['dn']))
			return

		# Ok here we have:
		# 1. Account currently not locked in OpenLDAP but in Samba/AD
		# 2. Lockout state has changed to unlocked at some pickled point in the past
		modlist.append((ldap.MOD_REPLACE, "lockoutTime", "0"))
		modlist.append((ldap.MOD_REPLACE, "badPasswordTime", "0"))
		ud.debug(ud.LDAP, ud.PROCESS, "%s: Marking account as unlocked in Samba/AD" % (function_name,))
	else:
		s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['lockoutTime', 'badPasswordTime'])
		lockoutTime = s4_object_attributes.get('lockoutTime', ['0'])[0]

		# Now object.get('new_ucs_object') may be a stale pickled state, so let's lookup the current OpenLDAP object state
		# Unfortunately "object" doesn't hold the current OpenLDAP DN, so we need to map back first
		ucs_object = s4connector._object_mapping(key, object)
		try:
			ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaAcctFlags', 'sambaBadPasswordTime'], required=True)
		except ldap.NO_SUCH_OBJECT:
			ud.debug(ud.LDAP, ud.WARN, "%s: The UCS object (%s) was not found. The object was removed." % (function_name, ucs_object['dn']))
			return
		sambaAcctFlags = ucs_object_attributes.get('sambaAcctFlags', [''])[0]
		if "L" not in sambaAcctFlags:
			## currently not locked any longer
			return

		sambaBadPasswordTime = ucs_object_attributes.get('sambaBadPasswordTime', [''])[0]
		if not sambaBadPasswordTime:
			ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is locked, but sambaBadPasswordTime is missing." % (function_name, ucs_object['dn']))
			return
		if sambaBadPasswordTime == "0":
			ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is locked, but sambaBadPasswordTime is 0." % (function_name, ucs_object['dn']))
			return
		if sambaBadPasswordTime == lockoutTime:
			## already locked
			return

		# Ok here we have:
		# 1. Account currently locked in OpenLDAP but not in Samba/AD
		# 2. Lockout state has changed to locked at some pickled point in the past
		modlist.append((ldap.MOD_REPLACE, "lockoutTime", sambaBadPasswordTime))
		modlist.append((ldap.MOD_REPLACE, "badPasswordTime", sambaBadPasswordTime))
		ud.debug(ud.LDAP, ud.PROCESS, "%s: Marking account as locked in Samba/AD" % (function_name,))
		ud.debug(ud.LDAP, ud.INFO, "%s: Setting lockoutTime to the value of sambaBadPasswordTime: %s" % (function_name, sambaBadPasswordTime))

	if modlist:
		ud.debug(ud.LDAP, ud.ALL, "%s: modlist: %s" % (function_name, modlist))
		s4connector.lo_s4.lo.modify_ext_s(compatible_modstring(object['dn']), modlist)
Example #23
0
 def delete_attribute(self, dn, key):
     self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)),
                          [(ldap.MOD_DELETE, key, None)],
                          serverctrls=self.serverctrls_for_add_and_modify)
Example #24
0
 def set_attribute(self, dn, key, value):
     self.lo.modify_s(
         s4.compatible_modstring(unicode(dn)),
         [(ldap.MOD_REPLACE, key, s4.compatible_modstring(unicode(value)))])
Example #25
0
 def remove_from_attribute(self, dn, key, value):
     self.lo.modify_ext_s(
         s4.compatible_modstring(unicode(dn)),
         [(ldap.MOD_DELETE, key, s4.compatible_modstring(unicode(value)))],
         serverctrls=self.serverctrls_for_add_and_modify)
Example #26
0
	def set_attribute(self, dn, key, value):
		self.lo.modify_s (s4.compatible_modstring (unicode (dn)),
						  [(ldap.MOD_REPLACE, key, s4.compatible_modstring (unicode (value)))])