350 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			350 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								from nameko.events import EventDispatcher, event_handler
							 | 
						||
| 
								 | 
							
								from nameko.rpc import rpc
							 | 
						||
| 
								 | 
							
								from configparser import ConfigParser
							 | 
						||
| 
								 | 
							
								from ldap3 import Server, ServerPool, Connection, ObjectDef, AttrDef, Reader, Writer
							 | 
						||
| 
								 | 
							
								from datetime import datetime
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# For testing
							 | 
						||
| 
								 | 
							
								from random import randint
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Read the config in the nameko.conf
							 | 
						||
| 
								 | 
							
								config = ConfigParser()
							 | 
						||
| 
								 | 
							
								config.read('nameko.conf')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Sanity check for config
							 | 
						||
| 
								 | 
							
								try:
							 | 
						||
| 
								 | 
							
								    mult_server = int(config['LDAP']['SERVERMULTIPLE'])
							 | 
						||
| 
								 | 
							
								# SERVERMULTIPLE is set to something not a number
							 | 
						||
| 
								 | 
							
								except:
							 | 
						||
| 
								 | 
							
								    exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
							 | 
						||
| 
								 | 
							
								# less than one server is not a sensible option
							 | 
						||
| 
								 | 
							
								if mult_server < 1:
							 | 
						||
| 
								 | 
							
								    exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Function to setup the server or serverpool
							 | 
						||
| 
								 | 
							
								def ldapservers():
							 | 
						||
| 
								 | 
							
								    # Just one server, no need for a pool
							 | 
						||
| 
								 | 
							
								    if mult_server == 1:
							 | 
						||
| 
								 | 
							
								        ldapserver = Server(config['LDAP']['LDAPSERVER1'], use_ssl=True)
							 | 
						||
| 
								 | 
							
								        return ldapserver
							 | 
						||
| 
								 | 
							
								    # Multiple servers, set up a pool
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        ldapserver = ServerPool(None)
							 | 
						||
| 
								 | 
							
								        for x in range(1, (mult_server+1)):
							 | 
						||
| 
								 | 
							
								            ins = Server(config['LDAP']['LDAPSERVER' + str(x)], use_ssl=True)
							 | 
						||
| 
								 | 
							
								            ldapserver.add(ins)
							 | 
						||
| 
								 | 
							
								        return ldapserver
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Since there's no reason why someone in ou=users shouldn't use the service,
							 | 
						||
| 
								 | 
							
								# here's the helper function to check whether an uid is in ou=customers or
							 | 
						||
| 
								 | 
							
								# ou=users
							 | 
						||
| 
								 | 
							
								# returns the full dn
							 | 
						||
| 
								 | 
							
								def user_or_customer(uid):
							 | 
						||
| 
								 | 
							
								    server = ldapservers()
							 | 
						||
| 
								 | 
							
								    conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP','LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								    conn.bind()
							 | 
						||
| 
								 | 
							
								    search_customers = conn.search('ou=customers,dc=ungleich,dc=ch', '(%s)' % uid)
							 | 
						||
| 
								 | 
							
								    if search_customers:
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        return '%s,ou=customers,dc=ungleich,dc=ch' % uid
							 | 
						||
| 
								 | 
							
								    search_users = conn.search('ou=users,dc=ungleich,dc=ch', '(%s)' % uid)
							 | 
						||
| 
								 | 
							
								    if search_users:
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        return '%s,ou=users,dc=ungleich,dc=ch' % uid
							 | 
						||
| 
								 | 
							
								    conn.unbind()
							 | 
						||
| 
								 | 
							
								    return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Get the objectclasses
							 | 
						||
| 
								 | 
							
								def objclasses(rdn, uid, connection):
							 | 
						||
| 
								 | 
							
								    # search for objectClasses
							 | 
						||
| 
								 | 
							
								    connection.search(rdn, '(%s)' % uid, attributes=['objectClass'])
							 | 
						||
| 
								 | 
							
								    objclass = []
							 | 
						||
| 
								 | 
							
								    # get the relevant data
							 | 
						||
| 
								 | 
							
								    tmp = connection.entries[0]['objectClass']
							 | 
						||
| 
								 | 
							
								    # This one sets up the array
							 | 
						||
| 
								 | 
							
								    for y in tmp:
							 | 
						||
| 
								 | 
							
								        objclass.append(y)
							 | 
						||
| 
								 | 
							
								    # return the array containing the objectClasses, like ['inetOrgPerson', 'posixAccount', 'ldapPublicKey']
							 | 
						||
| 
								 | 
							
								    return objclass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# checks if a user already exists in the LDAP
							 | 
						||
| 
								 | 
							
								class UserLookUp(object):
							 | 
						||
| 
								 | 
							
								    name = "userlookup"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def lookup(self, user):
							 | 
						||
| 
								 | 
							
								        # Setup the search parameter and connect to LDAP
							 | 
						||
| 
								 | 
							
								        LDAP_UID = 'uid=%s' % user
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP','LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        conn.bind()
							 | 
						||
| 
								 | 
							
								        # Strange result. It keeps complaining LDAP_UID not set if I try to directly
							 | 
						||
| 
								 | 
							
								        # substitute x and y to the if
							 | 
						||
| 
								 | 
							
								        # Searches for user in ou=customers and ou=users
							 | 
						||
| 
								 | 
							
								        x = conn.search('ou=customers,dc=ungleich,dc=ch', '(%s)' % LDAP_UID)
							 | 
						||
| 
								 | 
							
								        y = conn.search('ou=users,dc=ungleich,dc=ch', '(%s)' % LDAP_UID)
							 | 
						||
| 
								 | 
							
								        if x or y:
							 | 
						||
| 
								 | 
							
								            # return conn.entries[0] for first search result since we can assume uid is unique
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Info: UserLookUp] Searched for %s and found it\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            # return True since the user is already in LDAP
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								        # User not in LDAP, so just close it down, write the log and return False
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Info: UserLookUp] Searched for %s and not found it.\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Create a user in the LDAP. Assumes the checks are already in place for existing users
							 | 
						||
| 
								 | 
							
								class CreateUser(object):
							 | 
						||
| 
								 | 
							
								    name = "createuser"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def create_user(self, user, password, firstname, lastname, email):
							 | 
						||
| 
								 | 
							
								        # Creates a user with some basic data
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP','LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        if not conn.bind():
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error CreateUser] Could not connect to LDAPserver\n' % datetime.now() )
							 | 
						||
| 
								 | 
							
								            return "Could not connect to LDAP Server."
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        # set objectClasses for the new user
							 | 
						||
| 
								 | 
							
								        obj_new_user = ObjectDef(['inetOrgPerson', 'posixAccount', 'ldapPublicKey'], conn)
							 | 
						||
| 
								 | 
							
								        w = Writer(conn, obj_new_user)
							 | 
						||
| 
								 | 
							
								        dn = 'uid=%s,ou=users,dc=ungleich,dc=ch' % user
							 | 
						||
| 
								 | 
							
								        w.new(dn)
							 | 
						||
| 
								 | 
							
								        # Filling in some of the data
							 | 
						||
| 
								 | 
							
								        # required attributes are sn, cn, homeDirectory, uid (already handled by dn), uidNumber, gidNumber
							 | 
						||
| 
								 | 
							
								        w[0].givenName = firstname
							 | 
						||
| 
								 | 
							
								        w[0].sn = lastname
							 | 
						||
| 
								 | 
							
								        w[0].cn = firstname + " " + lastname
							 | 
						||
| 
								 | 
							
								        w[0].mail = email
							 | 
						||
| 
								 | 
							
								        w[0].userPassword = password
							 | 
						||
| 
								 | 
							
								        w[0].homeDirectory = '/home/%s' % user
							 | 
						||
| 
								 | 
							
								        # Set uidNumber as last used uidNumber+1
							 | 
						||
| 
								 | 
							
								        w[0].uidNumber = self.get_new_uid_number(conn)
							 | 
						||
| 
								 | 
							
								        # gidNumber for users created by userservice, nice and clear
							 | 
						||
| 
								 | 
							
								        w[0].gidNumber = 10004
							 | 
						||
| 
								 | 
							
								        if not w.commit():
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error CreateUser] Could not write new user %s to LDAP DB\n' % (datetime.now(), dn) )
							 | 
						||
| 
								 | 
							
								            return "Couldn't write data to the LDAP Server."
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        self.dispatch('ldap', '%s [Info CreateUser] %s created.\n' % (datetime.now(), dn) )
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Function to get the next uid number. Not elegant, but LAM does it too and didn't really find anything
							 | 
						||
| 
								 | 
							
								    # nicer. The sorted() seems to be quite efficient, so it shouldn't take too long even on larger arrays
							 | 
						||
| 
								 | 
							
								    def get_new_uid_number(self, conn):
							 | 
						||
| 
								 | 
							
								        conn.search('dc=ungleich,dc=ch', '(&(objectClass=posixAccount)(uidNumber=*))', attributes = [ 'uidNumber' ])
							 | 
						||
| 
								 | 
							
								        newuid = 0
							 | 
						||
| 
								 | 
							
								        uidlist = []
							 | 
						||
| 
								 | 
							
								        for c in conn.response:
							 | 
						||
| 
								 | 
							
								            uidlist.append(c['attributes']['uidNumber'])
							 | 
						||
| 
								 | 
							
								        # New uid is highest old uidnumber plus one
							 | 
						||
| 
								 | 
							
								        newuid = (sorted(uidlist)[len(uidlist)-1] + 1)
							 | 
						||
| 
								 | 
							
								        return newuid
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Returns some basic data from an user
							 | 
						||
| 
								 | 
							
								class GetUserData(object):
							 | 
						||
| 
								 | 
							
								    name = "getuserdata"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def get_data(self, user):
							 | 
						||
| 
								 | 
							
								        # Setup the search parameter and connect to LDAP
							 | 
						||
| 
								 | 
							
								        LDAP_UID = 'uid=%s' % user
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP', 'LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        conn.bind()
							 | 
						||
| 
								 | 
							
								        if not conn.bound:
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error GetUserData] Could not connect to LDAP server.\n' % datetime.now() )
							 | 
						||
| 
								 | 
							
								            return ("error", "Could not connect to LDAP server.", "", "")
							 | 
						||
| 
								 | 
							
								        rdn = user_or_customer(LDAP_UID)
							 | 
						||
| 
								 | 
							
								        if rdn == False:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Info GetUserData] Could not find user %s\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            return ("error", "Could not find the user.", "", "")
							 | 
						||
| 
								 | 
							
								        # Workaround because not all users have the same objectClasses
							 | 
						||
| 
								 | 
							
								        objclass = objclasses(rdn, LDAP_UID, conn)
							 | 
						||
| 
								 | 
							
								        obj = ObjectDef(objclass, conn)
							 | 
						||
| 
								 | 
							
								        # The Reader gets the data for the user
							 | 
						||
| 
								 | 
							
								        r = Reader(conn, obj, rdn)
							 | 
						||
| 
								 | 
							
								        r.search()
							 | 
						||
| 
								 | 
							
								        # Since the DN is basically confirmed by user_or_customer() it shouldn't throw an exception, but better check
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            x = r[0].sn
							 | 
						||
| 
								 | 
							
								        except:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error GetUserData] Could not open Reader for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								            return ("error", "Could not read data for user.", "", "")
							 | 
						||
| 
								 | 
							
								        # Putting the results into strings and then clean it up a bit if some attribute is not set in LDAP
							 | 
						||
| 
								 | 
							
								        (firstname, lastname, email) = (str(r[0].givenName), str(r[0].sn), str(r[0].mail))
							 | 
						||
| 
								 | 
							
								        if firstname == '[]':
							 | 
						||
| 
								 | 
							
								            firstname = 'No firstname given'
							 | 
						||
| 
								 | 
							
								        if lastname == '[]':
							 | 
						||
| 
								 | 
							
								            lastname = 'No lastname given'
							 | 
						||
| 
								 | 
							
								        if email == '[]':
							 | 
						||
| 
								 | 
							
								            email = 'No email given'
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        self.dispatch('ldap', '%s [Info GetUserData] Got data for %s  Firstname: %s  Lastname: %s  Email: %s\n' % (datetime.now(), rdn, firstname, lastname, email) )
							 | 
						||
| 
								 | 
							
								        return ("OK", firstname, lastname, email)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# change some (firstname, lastname, email) data for the user
							 | 
						||
| 
								 | 
							
								class ChangeUserData(object):
							 | 
						||
| 
								 | 
							
								    name = "changeuserdata"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def change_data(self, user, firstname, lastname, email):
							 | 
						||
| 
								 | 
							
								        LDAP_UID = 'uid=%s' % user
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        # Establish connection with a user who can change the data
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP', 'LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        if not conn.bind():
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangeUserData] Could not connect to LDAP server.\n' % datetime.now() )
							 | 
						||
| 
								 | 
							
								            return "Could not connect to LDAP server."
							 | 
						||
| 
								 | 
							
								        # get the DN of the user
							 | 
						||
| 
								 | 
							
								        rdn = user_or_customer(LDAP_UID)
							 | 
						||
| 
								 | 
							
								        if rdn == False:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Info ChangeUserData] User with %s not found.\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            return "Could not find user."
							 | 
						||
| 
								 | 
							
								        # Fix because not every user has the same objectClasses
							 | 
						||
| 
								 | 
							
								        objclass = objclasses(rdn, LDAP_UID, conn)
							 | 
						||
| 
								 | 
							
								        # Set up a reader for the user
							 | 
						||
| 
								 | 
							
								        obj = ObjectDef(objclass, conn)
							 | 
						||
| 
								 | 
							
								        r = Reader(conn, obj, rdn)
							 | 
						||
| 
								 | 
							
								        r.search()
							 | 
						||
| 
								 | 
							
								        # Again, user_or_customer() should prevent it from throwing an exception because it's a confirmed user
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            x = r[0].sn
							 | 
						||
| 
								 | 
							
								        except:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangeUserData] Could not open Reader for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								            return "Could not open the data of user."
							 | 
						||
| 
								 | 
							
								        # Opens a Writer instance prefilled with the old data
							 | 
						||
| 
								 | 
							
								        # We could check if something has changed, but since the form takes the old data as standard values, let's
							 | 
						||
| 
								 | 
							
								        # just update the relevant attributes
							 | 
						||
| 
								 | 
							
								        w = Writer.from_cursor(r)
							 | 
						||
| 
								 | 
							
								        w[0].sn = lastname
							 | 
						||
| 
								 | 
							
								        w[0].cn = firstname + " " + lastname
							 | 
						||
| 
								 | 
							
								        w[0].givenName = firstname
							 | 
						||
| 
								 | 
							
								        w[0].mail = email
							 | 
						||
| 
								 | 
							
								        # check if the data is written
							 | 
						||
| 
								 | 
							
								        if not w.commit():
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangeUserData] Could not write changes for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								            return "Could not write changes for user."
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        self.dispatch('ldap', '%s [Info ChangeUserData] Changed data for %s  Firstname: %s  Lastname: %s  Email: %s\n' % (datetime.now(), rdn, firstname, lastname, email) )
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# change the password for the user
							 | 
						||
| 
								 | 
							
								class ChangePassword(object):
							 | 
						||
| 
								 | 
							
								    name = "changepassword"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def change_password(self, user, newpassword):
							 | 
						||
| 
								 | 
							
								        LDAP_UID = 'uid=%s' % user
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP', 'LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        if not conn.bind():
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangePassword] Could not connect to LDAP server.\n' % datetime.now() )
							 | 
						||
| 
								 | 
							
								            return "Could not connect to LDAP server."
							 | 
						||
| 
								 | 
							
								        # check if uid=user is in either ou=customers or ou=users
							 | 
						||
| 
								 | 
							
								        rdn = user_or_customer(LDAP_UID)
							 | 
						||
| 
								 | 
							
								        if rdn == False:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangePassword] Could not find user %s\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            return "Could not find the user."
							 | 
						||
| 
								 | 
							
								        # Plus not everyone has the same objectClasses, so workaround
							 | 
						||
| 
								 | 
							
								        objclass = objclasses(rdn, LDAP_UID, conn)
							 | 
						||
| 
								 | 
							
								        obj = ObjectDef(objclass, conn)
							 | 
						||
| 
								 | 
							
								        # Set up a Reader for the DN
							 | 
						||
| 
								 | 
							
								        r = Reader(conn, obj, rdn)
							 | 
						||
| 
								 | 
							
								        r.search()
							 | 
						||
| 
								 | 
							
								        # Shouldn't throw an exception, since the user is confirmed to be there
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            x = r[0].sn
							 | 
						||
| 
								 | 
							
								        except:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangePassword] Could not open Reader for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								            return "Could not open the data for the user."
							 | 
						||
| 
								 | 
							
								        # Set up the writer and overwrite the attribute with the new password
							 | 
						||
| 
								 | 
							
								        w = Writer.from_cursor(r)
							 | 
						||
| 
								 | 
							
								        w[0].userPassword = newpassword
							 | 
						||
| 
								 | 
							
								        # Check to see if the change has gone through
							 | 
						||
| 
								 | 
							
								        if not w.commit():
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error ChangePassword] Could not write data for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								            return "Could not write data for the user."
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        self.dispatch('ldap', '%s [Info ChangePassword] Password changed for %s\n' % (datetime.now(), rdn) )
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Deletes a user from LDAP
							 | 
						||
| 
								 | 
							
								class DeleteUser(object):
							 | 
						||
| 
								 | 
							
								    name = "deleteuser"
							 | 
						||
| 
								 | 
							
								    dispatch = EventDispatcher()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @rpc
							 | 
						||
| 
								 | 
							
								    def delete_user(self, user):
							 | 
						||
| 
								 | 
							
								        LDAP_UID = 'uid=%s' % user
							 | 
						||
| 
								 | 
							
								        server = ldapservers()
							 | 
						||
| 
								 | 
							
								        conn = Connection(server, config['LDAP']['LDAPMANAGER'], config.get('LDAP', 'LDAPMANAGERPASSWORD', raw=True))
							 | 
						||
| 
								 | 
							
								        conn.bind()
							 | 
						||
| 
								 | 
							
								        if not conn.bound:
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error DeleteUser] Could not connect to LDAP server.\n' % datetime.now() )
							 | 
						||
| 
								 | 
							
								            return "Could not connect to LDAP server."
							 | 
						||
| 
								 | 
							
								        # again, check whether the uid= is in ou=users or ou=customers
							 | 
						||
| 
								 | 
							
								        dn = user_or_customer(LDAP_UID)
							 | 
						||
| 
								 | 
							
								        if dn == False:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error DeleteUser] Could not find the user %s\n' % (datetime.now(), LDAP_UID) )
							 | 
						||
| 
								 | 
							
								            return "Could not find the user."
							 | 
						||
| 
								 | 
							
								        # Check if the delete was successfull
							 | 
						||
| 
								 | 
							
								        deleted = conn.delete(dn)
							 | 
						||
| 
								 | 
							
								        if not deleted:
							 | 
						||
| 
								 | 
							
								            conn.unbind()
							 | 
						||
| 
								 | 
							
								            self.dispatch('ldap', '%s [Error DeleteUser] Could not delete %s\n' % (datetime.now(), dn) )
							 | 
						||
| 
								 | 
							
								            return "Could not delete the user."
							 | 
						||
| 
								 | 
							
								        conn.unbind()
							 | 
						||
| 
								 | 
							
								        self.dispatch('ldap', '%s [Info DeleteUser] Deleted %s\n' % (datetime.now(), dn) )
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# the class to log all the dispatches
							 | 
						||
| 
								 | 
							
								# for now everything gets logged into the same logfile, but 
							 | 
						||
| 
								 | 
							
								# I don't forsee that much traffic plus with timestamps and the class name 
							 | 
						||
| 
								 | 
							
								# in the log should be readable
							 | 
						||
| 
								 | 
							
								class Log(object):
							 | 
						||
| 
								 | 
							
								    name = "log"
							 | 
						||
| 
								 | 
							
								    ldaplog = config['System']['LOGDIR'] + '/ldap.log'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Gets all the dispatches with 'ldap' and writes them into the ldap.log 
							 | 
						||
| 
								 | 
							
								    @event_handler('userlookup', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('createuser', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('getuserdata', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('changeuserdata', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('passwordresetrequest', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('changepassword', 'ldap')
							 | 
						||
| 
								 | 
							
								    @event_handler('deleteuser', 'ldap')
							 | 
						||
| 
								 | 
							
								    def event_handler_ldap(self, payload):
							 | 
						||
| 
								 | 
							
								        f = open(self.ldaplog, mode='a', encoding='utf-8')
							 | 
						||
| 
								 | 
							
								        f.write(payload)
							 | 
						||
| 
								 | 
							
								        f.close
							 | 
						||
| 
								 | 
							
								
							 |