summaryrefslogtreecommitdiffstats
path: root/ipa-server
diff options
context:
space:
mode:
Diffstat (limited to 'ipa-server')
-rw-r--r--ipa-server/ipaserver/ipaldap.py20
-rw-r--r--ipa-server/xmlrpc-server/funcs.py47
-rw-r--r--ipa-server/xmlrpc-server/ipaxmlrpc.py6
3 files changed, 73 insertions, 0 deletions
diff --git a/ipa-server/ipaserver/ipaldap.py b/ipa-server/ipaserver/ipaldap.py
index 7268594a..08113b4c 100644
--- a/ipa-server/ipaserver/ipaldap.py
+++ b/ipa-server/ipaserver/ipaldap.py
@@ -35,6 +35,7 @@ import time
import operator
import struct
from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
+from ldap.modlist import modifyModlist
from ldap.ldapobject import SimpleLDAPObject
@@ -307,6 +308,25 @@ class IPAdmin(SimpleLDAPObject):
raise e
return "Success"
+ def updateEntry(self,dn,olduser,newuser):
+ """This wraps the mod function. It assumes that the entry is already
+ populated with all of the desired objectclasses and attributes"""
+
+ sctrl = self.__get_server_controls__()
+
+ # find the differences but don't remove attributes that are missing
+ # from the update
+ modlist = modifyModlist(olduser, newuser, None, 1)
+
+ try:
+ self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
+ self.modify_s(dn, modlist)
+ except ldap.ALREADY_EXISTS:
+ raise ldap.ALREADY_EXISTS
+ except ldap.LDAPError, e:
+ raise e
+ return "Success"
+
def __wrapmethods(self):
"""This wraps all methods of SimpleLDAPObject, so that we can intercept
the methods that deal with entries. Instead of using a raw list of tuples
diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py
index a17fe2f4..358f04f2 100644
--- a/ipa-server/xmlrpc-server/funcs.py
+++ b/ipa-server/xmlrpc-server/funcs.py
@@ -325,3 +325,50 @@ class IPAServer:
users.append(self.convert_entry(u))
return users
+
+ def update_user (self, args, newuser=None, 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]
+
+ # Should be able to get this from either the old or new user
+ # but just in case someone has decided to try changing it, use the
+ # original
+ try:
+ moddn = olduser['dn']
+ except KeyError, e:
+ raise xmlrpclib.Fault(4, "Old user has no dn")
+
+ if opts:
+ self.set_principal(opts['remoteuser'])
+
+ try:
+ proxydn = self.get_dn_from_principal(self.princ)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ try:
+ m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,proxydn)
+ res = m1.updateEntry(moddn, olduser, newuser)
+ _LDAPPool.releaseConn(m1)
+ return res
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, str(e))
diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py
index 963117f0..7d8529d2 100644
--- a/ipa-server/xmlrpc-server/ipaxmlrpc.py
+++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py
@@ -239,6 +239,11 @@ class ModXMLRPCRequestHandler(object):
def handle_request(self,req):
"""Handle a single XML-RPC request"""
+ # The LDAP connection pool is not thread-safe. Avoid problems and
+ # force the forked model for now.
+ if not apache.mpm_query(apache.AP_MPMQ_IS_FORKED):
+ raise Fault(3, "Apache must use the forked model")
+
# XMLRPC uses POST only. Reject anything else
if req.method != 'POST':
req.allow_methods(['POST'],1)
@@ -279,6 +284,7 @@ def handler(req, profiling=False):
h.register_function(f.get_add_schema)
h.register_function(f.get_all_users)
h.register_function(f.find_users)
+ h.register_function(f.update_user)
h.handle_request(req)
finally:
pass