diff options
-rw-r--r-- | ipa-admintools/ipa-deluser | 7 | ||||
-rw-r--r-- | ipa-admintools/ipa-finduser | 5 | ||||
-rw-r--r-- | ipa-admintools/ipa-usermod | 2 | ||||
-rw-r--r-- | ipa-python/ipaclient.py | 18 | ||||
-rw-r--r-- | ipa-python/rpcclient.py | 43 | ||||
-rw-r--r-- | ipa-python/user.py | 2 | ||||
-rw-r--r-- | ipa-server/ipaserver/__init__.py | 35 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/funcs.py | 114 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/ipaxmlrpc.py | 17 |
9 files changed, 102 insertions, 141 deletions
diff --git a/ipa-admintools/ipa-deluser b/ipa-admintools/ipa-deluser index c6d5a8d77..10d248062 100644 --- a/ipa-admintools/ipa-deluser +++ b/ipa-admintools/ipa-deluser @@ -49,8 +49,11 @@ def main(): try: client = ipaclient.IPAClient() - client.mark_user_deleted(args[1]) - print args[1] + " successfully deleted" + ret = client.mark_user_deleted(args[1]) + if (ret == "Success"): + print args[1] + " successfully deleted" + else: + print args[1] + " " + ret except xmlrpclib.Fault, f: print f.faultString return 1 diff --git a/ipa-admintools/ipa-finduser b/ipa-admintools/ipa-finduser index 4b1651c0b..167ac23d7 100644 --- a/ipa-admintools/ipa-finduser +++ b/ipa-admintools/ipa-finduser @@ -49,6 +49,11 @@ def main(): try: client = ipaclient.IPAClient() users = client.find_users(args[1], sattrs=['dn','uid','cn','homeDirectory']) + + if len(users) == 0: + print "No entries found for", args[1] + return 0 + for ent in users: attr = ent.attrList() diff --git a/ipa-admintools/ipa-usermod b/ipa-admintools/ipa-usermod index bcd06821d..3c9f8adc0 100644 --- a/ipa-admintools/ipa-usermod +++ b/ipa-admintools/ipa-usermod @@ -54,7 +54,7 @@ def main(): usage() client = ipaclient.IPAClient() - user = client.get_user(args[1]) + user = client.get_user_by_uid(args[1]) if options.gecos: user.setValue('gecos', options.gecos) diff --git a/ipa-python/ipaclient.py b/ipa-python/ipaclient.py index 44c61c6ae..d7450f5ca 100644 --- a/ipa-python/ipaclient.py +++ b/ipa-python/ipaclient.py @@ -54,13 +54,19 @@ class IPAClient: if self.local: self.transport.set_principal(princ) - def get_user(self,uid,sattrs=None): + def get_user_by_uid(self,uid,sattrs=None): """Get a specific user by uid. If sattrs is set then only those attributes will be returned.""" - result = self.transport.get_user(uid,sattrs) + result = self.transport.get_user_by_uid(uid,sattrs) return user.User(result) - def add_user(self,user): + def get_user_by_dn(self,dn,sattrs=None): + """Get a specific user by uid. If sattrs is set then only those + attributes will be returned.""" + result = self.transport.get_user_by_dn(dn,sattrs) + return user.User(result) + + def add_user(self,user,user_container=None): """Add a user. user is a ipa.user object""" realm = config.config.get_realm() @@ -87,7 +93,7 @@ class IPAClient: del user_dict['dn'] # convert to a regular dict before sending - result = self.transport.add_user(user_dict) + result = self.transport.add_user(user_dict, user_container) return result def get_all_users(self): @@ -107,10 +113,10 @@ class IPAClient: result = self.transport.get_add_schema() return result - def find_users(self, criteria, sattrs=None): + def find_users(self, criteria, sattrs=None, user_container=None): """Find users whose uid matches the criteria. Wildcards are acceptable. Returns a list of User objects.""" - result = self.transport.find_users(criteria, sattrs) + result = self.transport.find_users(criteria, sattrs, user_container) users = [] for (attrs) in result: diff --git a/ipa-python/rpcclient.py b/ipa-python/rpcclient.py index d5a2d4262..cd94eb99c 100644 --- a/ipa-python/rpcclient.py +++ b/ipa-python/rpcclient.py @@ -67,15 +67,29 @@ class RPCClient: return user - def get_user(self,username,sattrs=None): + def get_user_by_uid(self,uid,sattrs=None): """Get a specific user. If sattrs is not None then only those attributes will be returned. The result is a dict.""" server = self.setup_server() + if sattrs is None: + sattrs = "__NONE__" try: - if sattrs is not None: - result = server.get_user(username,sattrs) - else: - result = server.get_user(username) + result = server.get_user_by_uid(uid, sattrs) + except xmlrpclib.Fault, fault: + raise ipaerror.gen_exception(fault.faultCode, fault.faultString) + except socket.error, (value, msg): + raise xmlrpclib.Fault(value, msg) + + return result + + def get_user_by_dn(self,dn,sattrs=None): + """Get a specific user. If sattrs is not None then only those + attributes will be returned. The result is a dict.""" + server = self.setup_server() + if sattrs is None: + sattrs = "__NONE__" + try: + result = server.get_user_by_dn(dn, sattrs) except xmlrpclib.Fault, fault: raise ipaerror.gen_exception(fault.faultCode, fault.faultString) except socket.error, (value, msg): @@ -83,14 +97,17 @@ class RPCClient: return result - def add_user(self,user): + def add_user(self,user,user_container=None): """Add a new user. Takes as input a dict where the key is the attribute name and the value is either a string or in the case of a multi-valued field a list of values""" server = self.setup_server() + + if user_container is None: + user_container = "__NONE__" try: - result = server.add_user(user) + result = server.add_user(user, user_container) except xmlrpclib.Fault, fault: raise ipaerror.gen_exception(fault.faultCode, fault.faultString) except socket.error, (value, msg): @@ -128,16 +145,18 @@ class RPCClient: return result - def find_users (self, criteria, sattrs=None): + def find_users (self, criteria, sattrs=None, user_container=None): """Return a list containing a User object for each user that matches the criteria.""" server = self.setup_server() try: - if sattrs is not None: - result = server.find_users(criteria, sattrs) - else: - result = server.find_users(criteria) + # None values are not allowed in XML-RPC + if sattrs is None: + sattrs = "__NONE__" + if user_container is None: + user_container = "__NONE__" + result = server.find_users(criteria, sattrs, user_container) except xmlrpclib.Fault, fault: raise ipaerror.gen_exception(fault.faultCode, fault.faultString) except socket.error, (value, msg): diff --git a/ipa-python/user.py b/ipa-python/user.py index dd0afb578..9d547e80d 100644 --- a/ipa-python/user.py +++ b/ipa-python/user.py @@ -33,7 +33,7 @@ class User: if isinstance(entrydata,tuple): self.dn = entrydata[0] self.data = ldap.cidict.cidict(entrydata[1]) - elif isinstance(entrydata,str): + elif isinstance(entrydata,str) or isinstance(entrydata,unicode): self.dn = entrydata self.data = ldap.cidict.cidict() elif isinstance(entrydata,dict): diff --git a/ipa-server/ipaserver/__init__.py b/ipa-server/ipaserver/__init__.py index 6d254d6af..6aced0db7 100644 --- a/ipa-server/ipaserver/__init__.py +++ b/ipa-server/ipaserver/__init__.py @@ -20,38 +20,3 @@ # __all__ = ["dsinstance", "krbinstance"] - -# -# Functions common for the XML RPC client and server -# -# Authors: -# Mike McLean <mikem@redhat.com> (from koji) - -# functions for encoding/decoding optional arguments - -def encode_args(*args,**opts): - """The function encodes optional arguments as regular arguments. - - This is used to allow optional arguments in xmlrpc calls - Returns a tuple of args - """ - if opts: - opts['__starstar'] = True - args = args + (opts,) - return args - -def decode_args(*args): - """Decodes optional arguments from a flat argument list - - Complementary to encode_args - Returns a tuple (args,opts) where args is a tuple and opts is a dict - """ - opts = {} - if len(args) > 0: - last = args[-1] - if type(last) == dict and last.get('__starstar',False): - del last['__starstar'] - opts = last - args = args[:-1] - return args,opts - diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index ebf28af39..0af0f5ef4 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -36,6 +36,8 @@ import re # Need a global to store this between requests _LDAPPool = None +DefaultContainer = "ou=users,ou=default" + # # Apache runs in multi-process mode so each process will have its own # connection. This could theoretically drive the total number of connections @@ -96,10 +98,10 @@ class IPAServer: # Convert to LDIF entry = str(ent) - + # Strip off any junk entry = entry.strip() - + # Don't need to identify binary fields and this breaks the parser so # remove double colons entry = entry.replace('::', ':') @@ -123,67 +125,49 @@ class IPAServer: return user - def get_user (self, args, sattrs=None, opts=None): + def __get_user (self, base, filter, sattrs=None, opts=None): """Get a specific user's entry. Return as a dict of values. Multi-valued fields are represented as lists. """ global _LDAPPool ent="" - # The XML-RPC server marshals the arguments into one variable - # while the direct caller has them separate. So do a little - # bit of gymnastics to figure things out. There has to be a - # better way, so FIXME - if isinstance(args,tuple): - opts = sattrs - if len(args) == 2: - username = args[0] - sattrs = args[1] - else: - username = args - sattrs = None - else: - username = args - if opts: self.set_principal(opts['remoteuser']) - if (isinstance(username, tuple)): - username = username[0] dn = self.get_dn_from_principal(self.princ) - filter = "(uid=" + username + ")" - m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - ent = m1.getEntry(self.basedn, self.scope, filter, sattrs) + ent = m1.getEntry(base, self.scope, filter, sattrs) _LDAPPool.releaseConn(m1) return self.convert_entry(ent) + + def get_user_by_uid (self, uid, sattrs=None, opts=None): + """Get a specific user's entry. Return as a dict of values. + Multi-valued fields are represented as lists. + """ + + filter = "(uid=" + uid + ")" + return self.__get_user(self.basedn, filter, sattrs, opts) - def add_user (self, args, user_container="ou=users,ou=default",opts=None): + def get_user_by_dn (self, dn, sattrs=None, opts=None): + """Get a specific user's entry. Return as a dict of values. + Multi-valued fields are represented as lists. + """ + + filter = "(objectClass=*)" + return self.__get_user(dn, filter, sattrs, opts) + + def add_user (self, user, user_container=None, opts=None): """Add a user in LDAP. Takes as input a dict where the key is the attribute name and the value is either a string or in the case of a multi-valued field a list of values. user_container sets where in the tree the user is placed.""" global _LDAPPool - # The XML-RPC server marshals the arguments into one variable - # while the direct caller has them separate. So do a little - # bit of gymnastics to figure things out. There has to be a - # better way, so FIXME - if isinstance(args,tuple): - opts = user_container - if len(args) == 2: - user = args[0] - user_container = args[1] - else: - user = args - user_container = "ou=users,ou=default" - else: - user = args - - if (isinstance(user, tuple)): - user = user[0] + if user_container is None: + user_container = DefaultContainer dn="uid=%s,%s,%s" % (user['uid'], user_container,self.basedn) entry = ipaserver.ipaldap.Entry(dn) @@ -283,26 +267,14 @@ class IPAServer: return users - def find_users (self, args, sattrs=None, opts=None): + def find_users (self, criteria, sattrs=None, user_container=None, opts=None): """Return a list containing a User object for each existing user that matches the criteria. """ global _LDAPPool - # The XML-RPC server marshals the arguments into one variable - # while the direct caller has them separate. So do a little - # bit of gymnastics to figure things out. There has to be a - # better way, so FIXME - if isinstance(args,tuple): - opts = sattrs - if len(args) == 2: - criteria = args[0] - sattrs = args[1] - else: - criteria = args - sattrs = None - else: - criteria = args + if user_container is None: + user_container = DefaultContainer if opts: self.set_principal(opts['remoteuser']) @@ -319,9 +291,10 @@ class IPAServer: # FIXME: Is this the filter we want or do we want to do searches of # cn as well? Or should the caller pass in the filter? filter = "(|(uid=%s)(cn=%s))" % (criteria, criteria) + basedn = user_container + "," + self.basedn try: m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn) - results = m1.getList(self.basedn, self.scope, filter, sattrs) + results = m1.getList(basedn, self.scope, filter, sattrs) _LDAPPool.releaseConn(m1) except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): results = [] @@ -343,27 +316,10 @@ class IPAServer: return new_dict - def update_user (self, args, newuser=None, opts=None): + def update_user (self, olduser, newuser, opts=None): """Update a user in LDAP""" global _LDAPPool - # The XML-RPC server marshals the arguments into one variable - # while the direct caller has them separate. So do a little - # bit of gymnastics to figure things out. There has to be a - # better way, so FIXME - if isinstance(args,tuple): - opts = newuser - if len(args) == 2: - olduser = args[0] - newuser = args[1] - else: - olduser = args - - if (isinstance(olduser, tuple)): - olduser = olduser[0] - if (isinstance(newuser, tuple)): - newuser = newuser[0] - olduser = self.convert_scalar_values(olduser) newuser = self.convert_scalar_values(newuser) @@ -385,22 +341,22 @@ class IPAServer: _LDAPPool.releaseConn(m1) return res - def mark_user_deleted (self, args, opts=None): + def mark_user_deleted (self, uid, opts=None): """Mark a user as inactive in LDAP. We aren't actually deleting users here, just making it so they can't log in, etc.""" global _LDAPPool - uid = args[0] - if opts: self.set_principal(opts['remoteuser']) proxydn = self.get_dn_from_principal(self.princ) - user = self.get_user(uid, ['dn', 'nsAccountlock'], opts) + user = self.get_user_by_uid(uid, ['dn', 'uid', 'nsAccountlock'], opts) # Are we doing an add or replace operation? if user.has_key('nsaccountlock'): + if user['nsaccountlock'] == "true": + return "already marked as deleted" has_key = True else: has_key = False diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py index be4762c35..7998dd7e0 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -133,7 +133,9 @@ class ModXMLRPCRequestHandler(object): opts={} opts['remoteuser'] = remoteuser - params = ipaserver.encode_args(params, opts) + # Tack onto the end of the passed-in arguments any options we also + # need + params = params + (opts,) # special case # if method == "get_user": @@ -164,9 +166,13 @@ class ModXMLRPCRequestHandler(object): func = self.funcs.get(method,None) if func is None: raise Fault(1, "Invalid method: %s" % method) - params,opts = ipaserver.decode_args(*params) - - ret = func(*params,**opts) + + args = list(params) + for i in range(len(args)): + if args[i] == '__NONE__': + args[i] = None + + ret = func(*args) return ret @@ -281,7 +287,8 @@ def handler(req, profiling=False): try: f = funcs.IPAServer() h = ModXMLRPCRequestHandler() - h.register_function(f.get_user) + h.register_function(f.get_user_by_uid) + h.register_function(f.get_user_by_dn) h.register_function(f.add_user) h.register_function(f.get_add_schema) h.register_function(f.get_all_users) |