mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Enable LDAP SASL authentication using a forwarded kerberos ticket
Handle both SASL auth and proxied authentication Refactor LDAP connection code to be simpler Other small bug fixes
This commit is contained in:
parent
82943c31de
commit
9b30f46744
@ -50,7 +50,9 @@ def main():
|
||||
client = ipaclient.IPAClient()
|
||||
users = client.find_users(args[1], sattrs=['dn','uid','cn','homeDirectory'])
|
||||
|
||||
if len(users) == 0:
|
||||
counter = users[0]
|
||||
users = users[1:]
|
||||
if counter == 0:
|
||||
print "No entries found for", args[1]
|
||||
return 0
|
||||
|
||||
|
@ -59,6 +59,9 @@ def main():
|
||||
except ipa.ipaerror.IPAError, e:
|
||||
print "%s" % e.message
|
||||
return 1
|
||||
except kerberos.GSSError, e:
|
||||
print "Could not initialize GSSAPI: %s/%s" % (e[0][0][0], e[0][1][0])
|
||||
return 1
|
||||
|
||||
if options.gecos:
|
||||
user.setValue('gecos', options.gecos)
|
||||
@ -79,6 +82,9 @@ def main():
|
||||
except xmlrpclib.ProtocolError, e:
|
||||
print "Unable to connect to IPA server: %s" % (e.errmsg)
|
||||
return 1
|
||||
except ipa.ipaerror.IPAError, e:
|
||||
print "%s" % (e.message)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
@ -35,13 +35,14 @@ import cStringIO
|
||||
import time
|
||||
import operator
|
||||
import struct
|
||||
import ldap.sasl
|
||||
from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
|
||||
from ldap.modlist import modifyModlist
|
||||
|
||||
from ldap.ldapobject import SimpleLDAPObject
|
||||
|
||||
from ipa import ipaerror, ipautil
|
||||
|
||||
# Global variable to define SASL auth
|
||||
sasl_auth = ldap.sasl.sasl({},'GSSAPI')
|
||||
|
||||
class Entry:
|
||||
"""This class represents an LDAP Entry object. An LDAP entry consists of a DN
|
||||
and a list of attributes. Each attribute consists of a name and a list of
|
||||
@ -196,22 +197,34 @@ class IPAdmin(SimpleLDAPObject):
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
|
||||
|
||||
def __localinit__(self):
|
||||
SimpleLDAPObject.__init__(self,'ldaps://%s:%d' % (self.host,self.port))
|
||||
"""If a CA certificate is provided then it is assumed that we are
|
||||
doing SSL client authentication with proxy auth.
|
||||
|
||||
If a CA certificate is not present then it is assumed that we are
|
||||
using a forwarded kerberos ticket for SASL auth. SASL provides
|
||||
its own encryption.
|
||||
"""
|
||||
if self.cacert is not None:
|
||||
SimpleLDAPObject.__init__(self,'ldaps://%s:%d' % (self.host,self.port))
|
||||
else:
|
||||
SimpleLDAPObject.__init__(self,'ldap://%s:%d' % (self.host,self.port))
|
||||
|
||||
def __init__(self,host,port,cacert,bindcert,bindkey,proxydn=None):
|
||||
"""We just set our instance variables and wrap the methods - the real work is
|
||||
done in __localinit__ and __initPart2 - these are separated out this way so
|
||||
that we can call them from places other than instance creation e.g. when
|
||||
using the start command, we just need to reconnect, not create a new instance"""
|
||||
"""We just set our instance variables and wrap the methods - the real
|
||||
work is done in __localinit__ and __initPart2 - these are separated
|
||||
out this way so that we can call them from places other than
|
||||
instance creation e.g. when we just need to reconnect, not create a
|
||||
new instance"""
|
||||
# ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
|
||||
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,cacert)
|
||||
ldap.set_option(ldap.OPT_X_TLS_CERTFILE,bindcert)
|
||||
ldap.set_option(ldap.OPT_X_TLS_KEYFILE,bindkey)
|
||||
if cacert is not None:
|
||||
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,cacert)
|
||||
ldap.set_option(ldap.OPT_X_TLS_CERTFILE,bindcert)
|
||||
ldap.set_option(ldap.OPT_X_TLS_KEYFILE,bindkey)
|
||||
|
||||
self.__wrapmethods()
|
||||
self.port = port or 389
|
||||
self.sslport = 0
|
||||
self.host = host
|
||||
self.cacert = cacert
|
||||
self.bindcert = bindcert
|
||||
self.bindkey = bindkey
|
||||
self.proxydn = proxydn
|
||||
@ -251,6 +264,12 @@ class IPAdmin(SimpleLDAPObject):
|
||||
def set_proxydn(self, proxydn):
|
||||
self.proxydn = proxydn
|
||||
|
||||
def set_keytab(self, keytab):
|
||||
if keytab is not None:
|
||||
os.environ["KRB5CCNAME"] = keytab
|
||||
self.sasl_interactive_bind_s("", sasl_auth)
|
||||
self.proxydn = None
|
||||
|
||||
def getEntry(self,*args):
|
||||
"""This wraps the search function. It is common to just get one entry"""
|
||||
|
||||
@ -346,7 +365,8 @@ class IPAdmin(SimpleLDAPObject):
|
||||
sctrl = self.__get_server_controls__()
|
||||
|
||||
try:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
if sctrl is not None:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
self.add_s(*args)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE)
|
||||
@ -366,7 +386,8 @@ class IPAdmin(SimpleLDAPObject):
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_EMPTY_MODLIST)
|
||||
|
||||
try:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
if sctrl is not None:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
self.modify_s(dn, modlist)
|
||||
# this is raised when a 'delete' attribute isn't found.
|
||||
# it indicates the previous attribute was removed by another
|
||||
@ -428,7 +449,8 @@ class IPAdmin(SimpleLDAPObject):
|
||||
modlist.append((operation, "nsAccountlock", "true"))
|
||||
|
||||
try:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
if sctrl is not None:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
self.modify_s(dn, modlist)
|
||||
except ldap.LDAPError, e:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
|
||||
@ -440,7 +462,8 @@ class IPAdmin(SimpleLDAPObject):
|
||||
sctrl = self.__get_server_controls__()
|
||||
|
||||
try:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
if sctrl is not None:
|
||||
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
|
||||
self.delete_s(*args)
|
||||
except ldap.LDAPError, e:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
|
||||
|
@ -47,20 +47,31 @@ DefaultGroupContainer = "cn=groups,cn=accounts"
|
||||
# this is not anticipated.
|
||||
class IPAConnPool:
|
||||
def __init__(self):
|
||||
self.numentries = 0
|
||||
self.freelist = []
|
||||
|
||||
def getConn(self, host, port, bindca, bindcert, bindkey, proxydn=None):
|
||||
self.numentries = self.numentries + 1
|
||||
def getConn(self, host, port, bindca, bindcert, bindkey, proxydn=None, keytab=None):
|
||||
conn = None
|
||||
if len(self.freelist) > 0:
|
||||
conn = self.freelist.pop()
|
||||
else:
|
||||
for i in range(len(self.freelist)):
|
||||
c = self.freelist[i]
|
||||
if ((c.host == host) and (c.port == port)):
|
||||
conn = self.freelist.pop(i)
|
||||
break
|
||||
if conn is None:
|
||||
conn = ipaserver.ipaldap.IPAdmin(host,port,bindca,bindcert,bindkey)
|
||||
conn.set_proxydn(proxydn)
|
||||
if proxydn is not None:
|
||||
conn.set_proxydn(proxydn)
|
||||
else:
|
||||
conn.set_keytab(keytab)
|
||||
return conn
|
||||
|
||||
def releaseConn(self, conn):
|
||||
self.freelist.append(conn)
|
||||
# We can't re-use SASL connections. If proxydn is None it means
|
||||
# we have a keytab set. See ipaldap.set_keytab
|
||||
if conn.proxydn is None:
|
||||
conn.unbind_s()
|
||||
else:
|
||||
self.freelist.append(conn)
|
||||
|
||||
class IPAServer:
|
||||
|
||||
@ -68,7 +79,8 @@ class IPAServer:
|
||||
global _LDAPPool
|
||||
# FIXME, this needs to be auto-discovered
|
||||
self.host = 'localhost'
|
||||
self.port = 636
|
||||
self.port = 389
|
||||
self.sslport = 636
|
||||
self.bindcert = "/usr/share/ipa/cert.pem"
|
||||
self.bindkey = "/usr/share/ipa/key.pem"
|
||||
self.bindca = "/usr/share/ipa/cacert.asc"
|
||||
@ -79,24 +91,84 @@ class IPAServer:
|
||||
self.basedn = ipa.ipautil.realm_to_suffix(ipa.config.config.get_realm())
|
||||
self.scope = ldap.SCOPE_SUBTREE
|
||||
self.princ = None
|
||||
self.keytab = None
|
||||
|
||||
def set_principal(self, princ):
|
||||
self.princ = princ
|
||||
|
||||
def set_keytab(self, keytab):
|
||||
self.keytab = keytab
|
||||
|
||||
def get_dn_from_principal(self, princ):
|
||||
"""Given a kerberls principal get the LDAP uid"""
|
||||
"""Given a kerberos principal get the LDAP uid"""
|
||||
global _LDAPPool
|
||||
|
||||
filter = "(krbPrincipalName=" + princ + ")"
|
||||
# The only anonymous search we should have
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,None)
|
||||
conn = _LDAPPool.getConn(self.host,self.sslport,self.bindca,self.bindcert,self.bindkey,None,None)
|
||||
try:
|
||||
ent = m1.getEntry(self.basedn, self.scope, filter, ['dn'])
|
||||
ent = conn.getEntry(self.basedn, self.scope, filter, ['dn'])
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
_LDAPPool.releaseConn(conn)
|
||||
|
||||
return "dn:" + ent.dn
|
||||
|
||||
def __setup_connection(self, opts):
|
||||
"""Set up common things done in the connection.
|
||||
If there is a keytab then return None as the proxy dn and the keytab
|
||||
otherwise return the proxy dn and None as the keytab.
|
||||
|
||||
We only want one or the other used at one time and we prefer
|
||||
the keytab. So if there is a keytab, return that and None for
|
||||
proxy dn to make calling getConn() easier.
|
||||
"""
|
||||
|
||||
if opts:
|
||||
if opts.get('keytab'):
|
||||
self.set_keytab(opts['keytab'])
|
||||
self.set_principal(None)
|
||||
else:
|
||||
self.set_keytab(None)
|
||||
self.set_principal(opts['remoteuser'])
|
||||
else:
|
||||
self.set_keytab(None)
|
||||
# The caller should have already set the principal
|
||||
|
||||
if self.princ is not None:
|
||||
return self.get_dn_from_principal(self.princ), None
|
||||
else:
|
||||
return None, self.keytab
|
||||
|
||||
def getConnection(self, opts):
|
||||
"""Wrapper around IPAConnPool.getConn() so we don't have to pass
|
||||
around self.* every time a connection is needed.
|
||||
|
||||
For SASL connections (where we have a keytab) we can't set
|
||||
the SSL variables for certificates. It confuses the ldap
|
||||
module.
|
||||
"""
|
||||
global _LDAPPool
|
||||
|
||||
(proxy_dn, keytab) = self.__setup_connection(opts)
|
||||
|
||||
if keytab is not None:
|
||||
bindca = None
|
||||
bindcert = None
|
||||
bindkey = None
|
||||
port = self.port
|
||||
else:
|
||||
bindca = self.bindca
|
||||
bindcert = self.bindcert
|
||||
bindkey = self.bindkey
|
||||
port = self.sslport
|
||||
|
||||
return _LDAPPool.getConn(self.host,port,bindca,bindcert,bindkey,proxy_dn,keytab)
|
||||
|
||||
def releaseConnection(self, conn):
|
||||
global _LDAPPool
|
||||
|
||||
_LDAPPool.releaseConn(conn)
|
||||
|
||||
def convert_entry(self, ent):
|
||||
entry = dict(ent.data)
|
||||
entry['dn'] = ent.dn
|
||||
@ -110,24 +182,17 @@ class IPAServer:
|
||||
entry[key] = value[0]
|
||||
return entry
|
||||
|
||||
|
||||
def __get_entry (self, base, filter, sattrs=None, opts=None):
|
||||
"""Get a specific entry. Return as a dict of values.
|
||||
Multi-valued fields are represented as lists.
|
||||
"""
|
||||
global _LDAPPool
|
||||
ent=""
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
ent = m1.getEntry(base, self.scope, filter, sattrs)
|
||||
ent = conn.getEntry(base, self.scope, filter, sattrs)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
|
||||
return self.convert_entry(ent)
|
||||
|
||||
@ -137,8 +202,6 @@ class IPAServer:
|
||||
oldentry is a dict
|
||||
newentry is a dict
|
||||
"""
|
||||
global _LDAPPool
|
||||
|
||||
oldentry = self.convert_scalar_values(oldentry)
|
||||
newentry = self.convert_scalar_values(newentry)
|
||||
|
||||
@ -150,16 +213,11 @@ class IPAServer:
|
||||
except KeyError, e:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_MISSING_DN)
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
proxydn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,proxydn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = m1.updateEntry(moddn, oldentry, newentry)
|
||||
res = conn.updateEntry(moddn, oldentry, newentry)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
return res
|
||||
|
||||
def __safe_filter(self, criteria):
|
||||
@ -234,8 +292,6 @@ class IPAServer:
|
||||
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
|
||||
|
||||
if user_container is None:
|
||||
user_container = DefaultUserContainer
|
||||
|
||||
@ -288,16 +344,11 @@ class IPAServer:
|
||||
for u in user:
|
||||
entry.setValues(u, user[u])
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = m1.addEntry(entry)
|
||||
res = conn.addEntry(entry)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
return res
|
||||
|
||||
def get_add_schema (self):
|
||||
@ -348,20 +399,13 @@ class IPAServer:
|
||||
"""Return a list containing a User object for each
|
||||
existing user.
|
||||
"""
|
||||
global _LDAPPool
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
filter = "(objectclass=posixAccount)"
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
all_users = m1.getList(self.basedn, self.scope, filter, None)
|
||||
all_users = conn.getList(self.basedn, self.scope, filter, None)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
|
||||
users = []
|
||||
for u in all_users:
|
||||
@ -372,13 +416,6 @@ class IPAServer:
|
||||
def find_users (self, criteria, sattrs=None, opts=None):
|
||||
"""Returns a list: counter followed by the results.
|
||||
If the results are truncated, counter will be set to -1."""
|
||||
global _LDAPPool
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
# Assume the list of fields to search will come from a central
|
||||
# configuration repository. A good format for that would be
|
||||
# a comma-separated list of fields
|
||||
@ -394,21 +431,21 @@ class IPAServer:
|
||||
(exact_match_filter, partial_match_filter) = self.__generate_match_filters(
|
||||
search_fields, criteria_words)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
try:
|
||||
exact_results = m1.getListAsync(self.basedn, self.scope,
|
||||
exact_results = conn.getListAsync(self.basedn, self.scope,
|
||||
exact_match_filter, sattrs)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
exact_results = [0]
|
||||
|
||||
try:
|
||||
partial_results = m1.getListAsync(self.basedn, self.scope,
|
||||
partial_results = conn.getListAsync(self.basedn, self.scope,
|
||||
partial_match_filter, sattrs)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
partial_results = [0]
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
|
||||
exact_counter = exact_results[0]
|
||||
partial_counter = partial_results[0]
|
||||
@ -450,13 +487,6 @@ class IPAServer:
|
||||
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
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
proxydn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
user = self.get_user_by_uid(uid, ['dn', 'uid', 'nsAccountlock'], opts)
|
||||
|
||||
# Are we doing an add or replace operation?
|
||||
@ -467,11 +497,11 @@ class IPAServer:
|
||||
else:
|
||||
has_key = False
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,proxydn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = m1.inactivateEntry(user['dn'], has_key)
|
||||
res = conn.inactivateEntry(user['dn'], has_key)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
return res
|
||||
|
||||
def delete_user (self, uid, opts=None):
|
||||
@ -483,18 +513,15 @@ class IPAServer:
|
||||
The memberOf plugin handles removing the user from any other
|
||||
groups.
|
||||
"""
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
user_dn = self.get_user_by_uid(uid, ['dn', 'uid', 'objectclass'], opts)
|
||||
if user_dn is None:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
res = m1.deleteEntry(user_dn['dn'])
|
||||
_LDAPPool.releaseConn(m1)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = conn.deleteEntry(user_dn['dn'])
|
||||
finally:
|
||||
self.releaseConnection(conn)
|
||||
return res
|
||||
|
||||
# Group support
|
||||
@ -532,8 +559,6 @@ class IPAServer:
|
||||
attribute name and the value is either a string or in the case
|
||||
of a multi-valued field a list of values. group_container sets
|
||||
where in the tree the group is placed."""
|
||||
global _LDAPPool
|
||||
|
||||
if group_container is None:
|
||||
group_container = DefaultGroupContainer
|
||||
|
||||
@ -554,38 +579,26 @@ class IPAServer:
|
||||
for g in group:
|
||||
entry.setValues(g, group[g])
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = m1.addEntry(entry)
|
||||
res = conn.addEntry(entry)
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
|
||||
def find_groups (self, criteria, sattrs=None, opts=None):
|
||||
"""Return a list containing a User object for each
|
||||
existing group that matches the criteria.
|
||||
"""
|
||||
global _LDAPPool
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
criteria = self.__safe_filter(criteria)
|
||||
|
||||
filter = "(&(cn=%s)(objectClass=posixGroup))" % criteria
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
results = m1.getList(self.basedn, self.scope, filter, sattrs)
|
||||
results = conn.getList(self.basedn, self.scope, filter, sattrs)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
results = []
|
||||
finally:
|
||||
_LDAPPool.releaseConn(m1)
|
||||
self.releaseConnection(conn)
|
||||
|
||||
groups = []
|
||||
for u in results:
|
||||
@ -599,9 +612,6 @@ class IPAServer:
|
||||
group is the cn of the group to be added to
|
||||
"""
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
old_group = self.get_group_by_cn(group, None, opts)
|
||||
if old_group is None:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND)
|
||||
@ -652,9 +662,6 @@ class IPAServer:
|
||||
group is the cn of the group to be removed from
|
||||
"""
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
old_group = self.get_group_by_cn(group, None, opts)
|
||||
if old_group is None:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND)
|
||||
@ -718,19 +725,16 @@ class IPAServer:
|
||||
The memberOf plugin handles removing the group from any other
|
||||
groups.
|
||||
"""
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
dn = self.get_dn_from_principal(self.princ)
|
||||
|
||||
group = self.get_group_by_cn(group_cn, ['dn', 'cn'], opts)
|
||||
|
||||
if len(group) != 1:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND)
|
||||
|
||||
m1 = _LDAPPool.getConn(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
|
||||
res = m1.deleteEntry(group[0]['dn'])
|
||||
_LDAPPool.releaseConn(m1)
|
||||
conn = self.getConnection(opts)
|
||||
try:
|
||||
res = conn.deleteEntry(group[0]['dn'])
|
||||
finally:
|
||||
self.releaseConnection(conn)
|
||||
return res
|
||||
|
||||
def add_group_to_group(self, group, tgroup, opts=None):
|
||||
@ -739,9 +743,6 @@ class IPAServer:
|
||||
tgroup is the cn of the group to be added to
|
||||
"""
|
||||
|
||||
if opts:
|
||||
self.set_principal(opts['remoteuser'])
|
||||
|
||||
old_group = self.get_group_by_cn(tgroup, None, opts)
|
||||
if old_group is None:
|
||||
raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND)
|
||||
|
@ -126,13 +126,19 @@ class ModXMLRPCRequestHandler(object):
|
||||
def register_instance(self,instance):
|
||||
self.register_module(instance)
|
||||
|
||||
def _marshaled_dispatch(self, data, remoteuser):
|
||||
def _marshaled_dispatch(self, data, req):
|
||||
"""Dispatches an XML-RPC method from marshalled (XML) data."""
|
||||
|
||||
params, method = loads(data)
|
||||
|
||||
# Populate the Apache environment variables
|
||||
req.add_common_vars()
|
||||
|
||||
opts={}
|
||||
opts['remoteuser'] = remoteuser
|
||||
opts['remoteuser'] = req.user
|
||||
|
||||
if req.subprocess_env.get("KRB5CCNAME") is not None:
|
||||
opts['keytab'] = req.subprocess_env.get("KRB5CCNAME")
|
||||
|
||||
# Tack onto the end of the passed-in arguments any options we also
|
||||
# need
|
||||
@ -263,7 +269,7 @@ class ModXMLRPCRequestHandler(object):
|
||||
req.allow_methods(['POST'],1)
|
||||
raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED
|
||||
|
||||
response = self._marshaled_dispatch(req.read(), req.user)
|
||||
response = self._marshaled_dispatch(req.read(), req)
|
||||
|
||||
req.content_type = "text/xml"
|
||||
req.set_content_length(len(response))
|
||||
|
Loading…
Reference in New Issue
Block a user