- Abstracted client class to work directly or over RPC

- Add mod_auth_kerb and cyrus-sasl-gssapi to Requires
- Remove references to admin server in ipa-server-setupssl
- Generate a client certificate for the XML-RPC server to connect to LDAP with
- Create a keytab for Apache
- Create an ldif with a test user
- Provide a certmap.conf for doing SSL client authentication
- Update tools to use kerberos
- Add User class
This commit is contained in:
rcritten@redhat.com 2007-08-06 10:05:53 -04:00
parent 66ab69d0b2
commit 993f76fe60
26 changed files with 877 additions and 322 deletions

View File

@ -1,6 +1,6 @@
Name: freeipa-admintools
Version: 0.1.0
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -36,7 +36,12 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Update tools to do kerberos
- Add User class
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

View File

@ -1,6 +1,6 @@
Name: freeipa-admintools
Version: 0.1.0
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -36,7 +36,12 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Update tools to do kerberos
- Add User class
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

View File

@ -21,10 +21,11 @@
import sys
from optparse import OptionParser
import ipa
import ipa.rpcclient
import ipa.ipaclient as ipaclient
import ipa.config
import xmlrpclib
import kerberos
def usage():
print "ipa-adduser [-c|--gecos STRING] [-d|--directory STRING] [-f|--firstname STRING] [-l|--lastname STRING] user"
@ -73,10 +74,15 @@ def main():
user['loginshell'] = "/bin/bash"
try:
ipa.rpcclient.add_user(user)
print args[0] + " successfully added"
client = ipaclient.IPAClient()
client.add_user(user)
print args[1] + " successfully added"
except xmlrpclib.Fault, f:
print f.faultString
return 1
except kerberos.GSSError, e:
print "Could not initialize GSSAPI: %s/%s" % (e[0][0][0], e[0][1][0])
return 1
return 0

View File

@ -20,13 +20,12 @@
import sys
from optparse import OptionParser
import ipa
import ipa.rpcclient
import ipa.ipaclient as ipaclient
import ipa.config
import base64
import sys
import xmlrpclib
import kerberos
def usage():
print "ipa-finduser <uid>"
@ -48,16 +47,27 @@ def main():
usage()
try:
ent = ipa.rpcclient.get_user(args[1])
for name, value in ent.items():
if isinstance(value, str):
print name + ": " + value
client = ipaclient.IPAClient()
ent = client.get_user(args[1])
attr = ent.attrList()
print "dn: " + ent.dn
for a in attr:
value = ent.getValues(a)
if isinstance(value,str):
print a + ": " + value
else:
print name + ": "
for x in value:
print "\t" + x
print a + ": "
for l in value:
print "\t" + l
except xmlrpclib.Fault, fault:
print fault.faultString
return 1
except kerberos.GSSError, e:
print "Could not initialize GSSAPI: %s/%s" % (e[0][0][0], e[0][1][0])
return 1
return 0

View File

@ -1,6 +1,6 @@
Name: freeipa-python
Version: 0.1.0
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -42,6 +42,13 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Add User class
- Add kerberos authentication to the XML-RPC request made from tools.
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

View File

@ -1,6 +1,6 @@
Name: freeipa-python
Version: VERSION
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -42,6 +42,13 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Add User class
- Add kerberos authentication to the XML-RPC request made from tools.
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

87
ipa-python/ipaclient.py Normal file
View File

@ -0,0 +1,87 @@
#! /usr/bin/python -E
# Authors: Rob Crittenden <rcritten@redhat.com>
#
# Copyright (C) 2007 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; version 2 or later
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#!/usr/bin/python
import sys
sys.path.append("/usr/share/ipa")
from ipaserver import funcs
import ipa.rpcclient as rpcclient
import user
import ipa
import config
class IPAClient:
def __init__(self,local=None):
self.local = local
ipa.config.init_config()
if local:
self.transport = funcs.IPAServer()
# client needs to call set_principal(user@REALM)
else:
self.transport = rpcclient.RPCClient()
def set_principal(self,princ):
if self.local:
self.transport.set_principal(princ)
def get_user(self,uid):
result = self.transport.get_user(uid)
return user.User(result)
def add_user(self,user):
realm = config.config.get_realm()
# FIXME: This should be dynamic and can include just about anything
# Let us add in some missing attributes
if user.get('homeDirectory') is None:
user['homeDirectory'] ='/home/%s' % user['uid']
if user.get('gecos') is None:
user['gecos'] = user['uid']
# FIXME: This can be removed once the DS plugin is installed
user['uidNumber'] ='501'
# FIXME: What is the default group for users?
user['gidNumber'] ='501'
user['krbPrincipalName'] = "%s@%s" % (user['uid'], realm)
user['cn'] = "%s %s" % (user['givenName'], user['sn'])
if user.get('gn'):
del user['gn']
result = self.transport.add_user(user)
return result
def get_all_users(self):
result = self.transport.get_all_users()
all_users = []
for (attrs) in result:
if attrs is not None:
all_users.append(user.User(attrs))
return all_users
def get_add_schema(self):
result = self.transport.get_add_schema()
return result

View File

@ -0,0 +1,55 @@
#! /usr/bin/python -E
# Authors: Rob Crittenden <rcritten@redhat.com>
#
# Copyright (C) 2007 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; version 2 or later
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#!/usr/bin/python
import httplib
import xmlrpclib
import kerberos
from kerberos import GSSError
class KerbTransport(xmlrpclib.Transport):
"""Handles Kerberos Negotiation authentication to an XML-RPC server."""
def get_host_info(self, host):
host, extra_headers, x509 = xmlrpclib.Transport.get_host_info(self, host)
# Set the remote host principal
h = host
hostinfo = h.split(':')
service = "HTTP@" + hostinfo[0]
try:
rc, vc = kerberos.authGSSClientInit(service);
except kerberos.GSSError, e:
raise GSSError(e)
try:
kerberos.authGSSClientStep(vc, "");
except kerberos.GSSError, e:
raise GSSError(e)
extra_headers = [
("Authorization", "negotiate %s" % kerberos.authGSSClientResponse(vc) )
]
return host, extra_headers, x509

View File

@ -20,85 +20,101 @@
#!/usr/bin/python
try:
import krbV
except ImportError:
pass
import xmlrpclib
import socket
import config
from krbtransport import KerbTransport
from kerberos import GSSError
import os
import base64
import user
import ipa
# Some errors to catch
# http://cvs.fedora.redhat.com/viewcvs/ldapserver/ldap/servers/plugins/pam_passthru/README?root=dirsec&rev=1.6&view=auto
def server_url():
return "http://" + config.config.get_server() + "/ipa"
class RPCClient:
def setup_server():
return xmlrpclib.ServerProxy(server_url())
def __init__(self):
ipa.config.init_config()
def get_user(username):
"""Get a specific user"""
server = setup_server()
try:
result = server.get_user(username)
myuser = result
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
return None
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return None
def server_url(self):
return "http://" + config.config.get_server() + "/ipa"
return myuser
def setup_server(self):
return xmlrpclib.ServerProxy(self.server_url(), KerbTransport())
def add_user(user):
"""Add a new user"""
server = setup_server()
def convert_entry(self,ent):
# Convert into a dict. We need to handle multi-valued attributes as well
# so we'll convert those into lists.
user={}
for (k) in ent:
k = k.lower()
if user.get(k) is not None:
if isinstance(user[k],list):
user[k].append(ent[k].strip())
else:
first = user[k]
user[k] = ()
user[k].append(first)
user[k].append(ent[k].strip())
else:
user[k] = ent[k]
# FIXME: Get the realm from somewhere
realm = config.config.get_realm()
return user
# FIXME: This should be dynamic and can include just about anything
# Let us add in some missing attributes
if user.get('homeDirectory') is None:
user['homeDirectory'] ='/home/%s' % user['uid']
if user.get('gecos') is None:
user['gecos'] = user['uid']
def get_user(self,username):
"""Get a specific user"""
server = self.setup_server()
try:
result = server.get_user(username)
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
# FIXME: This can be removed once the DS plugin is installed
user['uidNumber'] ='501'
# FIXME: What is the default group for users?
user['gidNumber'] ='501'
user['krbPrincipalName'] = "%s@%s" % (user['uid'], realm)
user['cn'] = "%s %s" % (user['givenName'], user['sn'])
try:
result = server.add_user(user)
return result
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
return None
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return None
def get_add_schema():
"""Get the list of attributes we need to ask when adding a new
user.
"""
server = setup_server()
# FIXME: Hardcoded and designed for the TurboGears GUI. Do we want
# this for the CLI as well?
try:
result = server.get_add_schema()
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault, fault.faultString)
return None
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return None
def add_user(self,user):
"""Add a new user"""
server = self.setup_server()
return result
try:
result = server.add_user(user)
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return result
def get_add_schema(self):
"""Get the list of attributes we need to ask when adding a new
user.
"""
server = self.setup_server()
# FIXME: Hardcoded and designed for the TurboGears GUI. Do we want
# this for the CLI as well?
try:
result = server.get_add_schema()
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return result
def get_all_users (self):
"""Return a list containing a User object for each existing user."""
server = self.setup_server()
try:
result = server.get_all_users()
except xmlrpclib.Fault, fault:
raise xmlrpclib.Fault(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
raise xmlrpclib.Fault(value, msg)
return result

112
ipa-python/user.py Normal file
View File

@ -0,0 +1,112 @@
import ldap
import ldif
import re
import cStringIO
class User:
"""This class represents an IPA user. An LDAP entry consists of a DN
and a list of attributes. Each attribute consists of a name and a list of
values. For the time being I will maintain this.
In python-ldap, entries are returned as a list of 2-tuples.
Instance variables:
dn - string - the string DN of the entry
data - cidict - case insensitive dict of the attributes and values"""
def __init__(self,entrydata):
"""data is the raw data returned from the python-ldap result method,
which is a search result entry or a reference or None.
If creating a new empty entry, data is the string DN."""
if entrydata:
if isinstance(entrydata,tuple):
self.dn = entrydata[0]
self.data = ldap.cidict.cidict(entrydata[1])
elif isinstance(entrydata,str):
self.dn = entrydata
self.data = ldap.cidict.cidict()
elif isinstance(entrydata,dict):
self.dn = entrydata['dn']
del entrydata['dn']
self.data = ldap.cidict.cidict(entrydata)
else:
self.dn = ''
self.data = ldap.cidict.cidict()
def __nonzero__(self):
"""This allows us to do tests like if entry: returns false if there is no data,
true otherwise"""
return self.data != None and len(self.data) > 0
def hasAttr(self,name):
"""Return True if this entry has an attribute named name, False otherwise"""
return self.data and self.data.has_key(name)
def __getattr__(self,name):
"""If name is the name of an LDAP attribute, return the first value for that
attribute - equivalent to getValue - this allows the use of
entry.cn
instead of
entry.getValue('cn')
This also allows us to return None if an attribute is not found rather than
throwing an exception"""
return self.getValue(name)
def getValues(self,name):
"""Get the list (array) of values for the attribute named name"""
return self.data.get(name)
def getValue(self,name):
"""Get the first value for the attribute named name"""
value = self.data.get(name,[None])
if isinstance(value[0],list) or isinstance(value[0],tuple):
return value[0]
else:
return value
def setValue(self,name,*value):
"""Value passed in may be a single value, several values, or a single sequence.
For example:
ent.setValue('name', 'value')
ent.setValue('name', 'value1', 'value2', ..., 'valueN')
ent.setValue('name', ['value1', 'value2', ..., 'valueN'])
ent.setValue('name', ('value1', 'value2', ..., 'valueN'))
Since *value is a tuple, we may have to extract a list or tuple from that
tuple as in the last two examples above"""
if isinstance(value[0],list) or isinstance(value[0],tuple):
self.data[name] = value[0]
else:
self.data[name] = value
setValues = setValue
def toTupleList(self):
"""Convert the attrs and values to a list of 2-tuples. The first element
of the tuple is the attribute name. The second element is either a
single value or a list of values."""
return self.data.items()
def attrList(self):
"""Return a list of all attributes in the entry"""
return self.data.keys()
# def __str__(self):
# """Convert the Entry to its LDIF representation"""
# return self.__repr__()
#
# # the ldif class base64 encodes some attrs which I would rather see in raw form - to
# # encode specific attrs as base64, add them to the list below
# ldif.safe_string_re = re.compile('^$')
# base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData']
#
# def __repr__(self):
# """Convert the Entry to its LDIF representation"""
# sio = cStringIO.StringIO()
# # what's all this then? the unparse method will currently only accept
# # a list or a dict, not a class derived from them. self.data is a
# # cidict, so unparse barfs on it. I've filed a bug against python-ldap,
# # but in the meantime, we have to convert to a plain old dict for printing
# # I also don't want to see wrapping, so set the line width really high (1000)
# newdata = {}
# newdata.update(self.data)
# ldif.LDIFWriter(sio,User.base64_attrs,1000).unparse(self.dn,newdata)
# return sio.getvalue()

View File

@ -1,6 +1,6 @@
Name: freeipa-server
Version: 0.1.0
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -10,7 +10,7 @@ Source0: %{name}-%{version}.tgz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python python-ldap freeipa-python
Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python cyrus-sasl-gssapi
%define httpd_conf /etc/httpd/conf.d
@ -44,6 +44,17 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Add mod_auth_kerb and cyrus-sasl-gssapi to Requires
- Remove references to admin server in ipa-server-setupssl
- Generate a client certificate for the XML-RPC server to connect to LDAP with
- Create a keytab for Apache
- Create an ldif with a test user
- Provide a certmap.conf for doing SSL client authentication
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

View File

@ -1,6 +1,6 @@
Name: freeipa-server
Version: VERSION
Release: 1%{?dist}
Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@ -10,7 +10,7 @@ Source0: %{name}-%{version}.tgz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python python-ldap freeipa-python
Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python cyrus-sasl-gssapi
%define httpd_conf /etc/httpd/conf.d
@ -44,6 +44,17 @@ rm -rf %{buildroot}
%changelog
* Mon Aug 5 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-3
- Abstracted client class to work directly or over RPC
* Wed Aug 1 2007 Rob Crittenden <rcritten@redhat.com> - 0.1.0-2
- Add mod_auth_kerb and cyrus-sasl-gssapi to Requires
- Remove references to admin server in ipa-server-setupssl
- Generate a client certificate for the XML-RPC server to connect to LDAP with
- Create a keytab for Apache
- Create an ldif with a test user
- Provide a certmap.conf for doing SSL client authentication
* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
- Initial rpm version

View File

@ -6,6 +6,7 @@ install:
install -m 755 ipa-server-install $(SBINDIR)
install -m 755 ipa-server-setupssl $(SBINDIR)
$(MAKE) -C share $@
$(MAKE) -C test $@
clean:
$(MAKE) -C share $@

View File

@ -119,6 +119,9 @@ def main():
# Restart apache
run(["/sbin/service", "httpd", "restart"])
# Set apache to be on at boot
run(["/sbin/chkconfig", "httpd", "on"])
# Create the config file
fd = open("/etc/ipa/ipa.conf", "w")
fd.write("[defaults]\n")

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
if [ "$1" ] ; then
password=$1
@ -49,22 +49,14 @@ if [ -f $secdir/cert8.db ] ; then
needServerCert=1
fi
# look for admin server cert
if certutil -L -d $secdir -n "server-cert" 2> /dev/null ; then
echo "Using existing admin server-cert"
else
echo "No Admin Server Cert found - will create new one"
needASCert=1
fi
prefix="new-"
prefixarg="-P $prefix"
else
needCA=1
needServerCert=1
needASCert=1
fi
if test -z "$needCA" -a -z "$needServerCert" -a -z "$needASCert" ; then
if test -z "$needCA" -a -z "$needServerCert" ; then
echo "No certs needed - exiting"
exit 0
fi
@ -120,17 +112,17 @@ if test -n "$needServerCert" ; then
certutil -S $prefixarg -n "Server-Cert" -s "cn=$myhost,ou=Fedora Directory Server" -c "CA certificate" -t "u,u,u" -m 1001 -v 120 -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt
fi
if test -n "$needASCert" ; then
# Generate the admin server certificate
certutil -S $prefixarg -n "server-cert" -s "cn=$myhost,ou=Fedora Administration Server" -c "CA certificate" -t "u,u,u" -m 1002 -v 120 -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt
# 8. Generate the web service client certificate:
echo -e "0\n2\n9\nn\n0\n9\nn\n" | certutil -S $prefixarg -n webservice -s "uid=webservice, CN=Web Service, OU=Fedora Directory Server" -c "CA certificate" -t u,pu,u -m 1002 -v 120 -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt -1 -5
# export the admin server certificate/private key for import into its key/cert db
pk12util -d $secdir $prefixarg -o $secdir/adminserver.p12 -n server-cert -w $secdir/pwdfile.txt -k $secdir/pwdfile.txt
if test -n "$isroot" ; then
chown $uid:$gid $secdir/adminserver.p12
fi
chmod 400 $secdir/adminserver.p12
fi
pk12util -d $secdir $prefixarg -o $secdir/webservice.p12 -n "webservice" -w $secdir/pwdfile.txt -k $secdir/pwdfile.txt
openssl pkcs12 -in $secdir/webservice.p12 -clcerts -nokeys -out /usr/share/ipa/cert.pem -passin file:$secdir/pwdfile.txt
openssl pkcs12 -in $secdir/webservice.p12 -nocerts -nodes -out /usr/share/ipa/key.pem -passin file:$secdir/pwdfile.txt
cp -p $secdir/cacert.asc /usr/share/ipa
chown apache:apache /usr/share/ipa/cert.pem /usr/share/ipa/key.pem /usr/share/ipa/cacert.asc
chmod 600 /usr/share/ipa/cert.pem /usr/share/ipa/key.pem
# create the pin file
if [ ! -f $secdir/pin.txt ] ; then
@ -153,42 +145,6 @@ if [ -n "$prefix" ] ; then
mv $secdir/${prefix}key3.db $secdir/key3.db
fi
# create the admin server key/cert db
asprefix=admin-serv-
if [ ! -f ${asprefix}cert8.db ] ; then
certutil -N -d $secdir -P $asprefix -f $secdir/pwdfile.txt
if test -n "$isroot" ; then
chown $uid:$gid $secdir/admin-serv-*.db
fi
chmod 600 $secdir/admin-serv-*.db
fi
if test -n "$needASCert" ; then
# import the admin server key/cert
pk12util -d $secdir -P $asprefix -n server-cert -i $secdir/adminserver.p12 -w $secdir/pwdfile.txt -k $secdir/pwdfile.txt
# import the CA cert to the admin server cert db
certutil -A -d $secdir -P $asprefix -n "CA certificate" -t "CT,," -a -i $secdir/cacert.asc
fi
if [ ! -f $secdir/password.conf ] ; then
# create the admin server password file
echo 'internal:'`cat $secdir/pwdfile.txt` > $secdir/password.conf
if test -n "$isroot" ; then
chown $uid:$gid $secdir/password.conf
fi
chmod 400 $secdir/password.conf
fi
# tell admin server to use the password file
if [ -f ../admin-serv/config/nss.conf ] ; then
sed -e "s@^NSSPassPhraseDialog .*@NSSPassPhraseDialog file:`pwd`/password.conf@" ../admin-serv/config/nss.conf > /tmp/nss.conf && mv /tmp/nss.conf ../admin-serv/config/nss.conf
if test -n "$isroot" ; then
chown $uid:$gid ../admin-serv/config/nss.conf
fi
chmod 400 ../admin-serv/config/nss.conf
fi
# enable SSL in the directory server
ldapmodify -x -h localhost -p $ldapport -D "cn=Directory Manager" -w $password <<EOF

View File

@ -31,3 +31,26 @@ ou: groups
#objectClass: top
#ou: computers
dn: ou=special,$SUFFIX
changetype: add
objectClass: organizationalUnit
objectClass: top
ou: special
dn: uid=webservice,ou=special,$SUFFIX
changetype: add
uid: webservice
objectClass: account
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
cn: Web Service
sn: Service
dn: cn=admin,ou=groups,ou=default,$SUFFIX
changetype: add
description: ou=users administrators
objectClass: top
objectClass: groupofuniquenames
cn: admin

View File

@ -0,0 +1,82 @@
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
#
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
#
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception.
#
#
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#
#
# This file configures how a certificate is mapped to an LDAP entry. See the
# documentation for more information on this file.
#
# The format of this file is as follows:
# certmap <name> <issuerDN>
# <name>:<prop1> [<val1>]
# <name>:<prop2> [<val2>]
#
# Notes:
#
# 1. Mapping can be defined per issuer of a certificate. If mapping doesn't
# exists for a particular 'issuerDN' then the server uses the default
# mapping.
#
# 2. There must be an entry for <name>=default and issuerDN "default".
# This mapping is the default mapping.
#
# 3. '#' can be used to comment out a line.
#
# 4. DNComps & FilterComps are used to form the base DN and filter resp. for
# performing an LDAP search while mapping the cert to a user entry.
#
# 5. DNComps can be one of the following:
# commented out - take the user's DN from the cert as is
# empty - search the entire LDAP tree (DN == suffix)
# attr names - a comma separated list of attributes to form DN
#
# 6. FilterComps can be one of the following:
# commented out - set the filter to "objectclass=*"
# empty - set the filter to "objectclass=*"
# attr names - a comma separated list of attributes to form the filter
#
certmap default default
#default:DNComps
#default:FilterComps e, uid
#default:verifycert on
#default:CmapLdapAttr certSubjectDN
#default:library <path_to_shared_lib_or_dll>
#default:InitFn <Init function's name>
default:DNComps
default:FilterComps uid

View File

@ -6,3 +6,6 @@ aci: (targetattr!="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTP
aci: (targetattr="carLicense ||description ||displayName ||facsimileTelephoneNumber ||homePhone ||homePostalAddress ||initials ||jpegPhoto ||labeledURL ||mail ||mobile ||pager ||photo ||postOfficeBox ||postalAddress ||postalCode ||preferredDeliveryMethod ||preferredLanguage ||registeredAddress ||roomNumber | |secretary ||seeAlso ||st ||street ||telephoneNumber ||telexNumber ||title || userCertificate ||userPassword ||userSMIMECertificate ||x500UniqueIdentifier")(version 3.0; acl "Enable self write for common attributes"; allow (write) userdn="ldap:///self";)
aci: (targetattr="krbPrincipalKey")(version 3.0; acl "KDC System Account"; allow(read, search,compare)userdn="ldap:///uid=kdc,cn=kerberos,$SUFFIX";)
aci: (targetattr="*")(version 3.0; acl "Directory Administrators can manage all entries"; allow(all)groupdn="ldap:///cn=Directory Administrators,$SUFFIX";)
aci: (target="ldap:///uid=*,ou=users,ou=default,$SUFFIX")(targetattr="*")(version 3.0; acl "allowproxy-webservice"; allow (proxy) userdn="ldap:///uid=webservice,ou=special,$SUFFIX";)
aci: (target="ldap:///uid=*,ou=users,ou=default,$SUFFIX")(targetattr="*")(version 3.0; acl "admins can write entries"; allow(add,delete,write)groupdn="ldap:///cn=admin,ou=groups,ou=default,$SUFFIX";)
aci: (targetattr="userPrincipal")(version 3.0; acl "allow webservice to find users by kerberos principal name"; allow (read, search) userdn="ldap:///uid=webservice,ou=special,$SUFFIX";)

View File

@ -0,0 +1,8 @@
SHAREDIR = $(DESTDIR)/usr/share/ipa
install:
-mkdir -p $(SHAREDIR)
install -m 644 *.ldif $(SHAREDIR)
clean:
rm -f *~

View File

@ -1,5 +1,6 @@
# test, users, default, $REALM
dn: uid=test,ou=users,ou=default,$SUFFIX
changetype: add
uidNumber: 1001
uid: test
gecos: test
@ -13,8 +14,17 @@ shadowInactive: -1
shadowLastChange: 13655
shadowFlag: -1
gidNumber: 100
objectclass: krbPrincipalAux
objectclass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: account
objectClass: top
cn: test
cn: Test User
sn: User
krbPrincipalName: test@$REALM
dn: cn=admin,ou=groups,ou=default,$SUFFIX
changetype: modify
add: uniqueMember
uniqueMember: uid=test,ou=users,ou=default,$SUFFIX

View File

@ -88,8 +88,10 @@ class DsInstance:
self.__create_instance()
self.__add_default_schemas()
self.__enable_ssl()
self.__certmap_conf()
self.restart()
self.__add_default_layout()
self.__create_test_users()
def config_dirname(self):
if not self.serverid:
@ -136,7 +138,7 @@ class DsInstance:
args = ["/usr/sbin/setup-ds.pl", "--silent", "--logfile", "-", "-f", inf_fd.name]
logging.debug("calling setup-ds.pl")
else:
args = ["/usr/sbin/ds_newinst.pl", inf_fd.name]
args = ["/usr/bin/ds_newinst.pl", inf_fd.name]
logging.debug("calling ds_newinst.pl")
run(args)
logging.debug("completed creating ds instance")
@ -166,3 +168,21 @@ class DsInstance:
"-w", self.admin_password, "-f", inf_fd.name]
run(args)
logging.debug("done adding default ds layout")
def __create_test_users(self):
logging.debug("create test users ldif")
txt = template_file(SHARE_DIR + "test-users-template.ldif", self.sub_dict)
user_fd = open(SHARE_DIR+"test-users.ldif", "w")
user_fd.write(txt)
user_fd.close()
logging.debug("done creating test users ldif")
def __certmap_conf(self):
logging.debug("configuring certmap.conf for ds instance")
dirname = self.config_dirname()
certmap_conf = template_file(SHARE_DIR+"certmap.conf.template", self.sub_dict)
certmap_fd = open(dirname+"certmap.conf", "w+")
certmap_fd.write(certmap_conf)
certmap_fd.close()
logging.debug("done configuring certmap.conf for ds instance")

View File

@ -1,6 +1,6 @@
#! /usr/bin/python -E
# Authors: Rich Megginson <richm@redhat.com>
# Rob Crittenden <rcritten2redhat.com
# Rob Crittenden <rcritten@redhat.com
#
# Copyright (C) 2007 Red Hat
# see file 'COPYING' for use and warranty information
@ -33,6 +33,8 @@ import ldap
import cStringIO
import time
import operator
import struct
from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
from ldap.ldapobject import SimpleLDAPObject
@ -197,31 +199,25 @@ class IPAdmin(SimpleLDAPObject):
raise
def __localinit__(self):
SimpleLDAPObject.__init__(self,'ldap://%s:%d' % (self.host,self.port))
# see if binddn is a dn or a uid that we need to lookup
if self.binddn and not IPAdmin.is_a_dn(self.binddn):
self.simple_bind("","") # anon
ent = self.getEntry(IPAdmin.CFGSUFFIX, ldap.SCOPE_SUBTREE,
"(uid=%s)" % self.binddn,
['uid'])
if ent:
self.binddn = ent.dn
else:
print "Error: could not find %s under %s" % (self.binddn, IPAdmin.CFGSUFFIX)
self.simple_bind(self.binddn,self.bindpw)
# self.__initPart2()
SimpleLDAPObject.__init__(self,'ldaps://%s:%d' % (self.host,self.port))
def __init__(self,host,port,binddn,bindpw):
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"""
# 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)
self.__wrapmethods()
self.port = port or 389
self.sslport = 0
self.host = host
self.binddn = binddn
self.bindpw = bindpw
self.bindcert = bindcert
self.bindkey = bindkey
self.proxydn = proxydn
# see if is local or not
host1 = IPAdmin.getfqdn(host)
host2 = IPAdmin.getfqdn()
@ -237,7 +233,22 @@ class IPAdmin(SimpleLDAPObject):
def getEntry(self,*args):
"""This wraps the search function. It is common to just get one entry"""
res = self.search(*args)
# 0x04 = Octet String
# 4|0x80 sets the length of the length at 4 bytes
# the struct() gets us the length in bytes of string s
# s is the proxy dn to send
if self.proxydn is not None:
proxydn = chr(0x04) + chr(4|0x80) + struct.pack('l', socket.htonl(len(self.proxydn))) + self.proxydn;
# Create the proxy control
sctrl=[]
sctrl.append(LDAPControl('2.16.840.1.113730.3.4.18',True,proxydn))
else:
sctrl=None
res = self.search_ext(args[0], args[1], filterstr=args[2], serverctrls=sctrl)
type, obj = self.result(res)
if not obj:
raise NoSuchEntryError("no such entry for " + str(args))
@ -246,10 +257,38 @@ class IPAdmin(SimpleLDAPObject):
else: # assume list/tuple
return obj[0]
def getList(self,*args):
"""This wraps the search function to find all users."""
res = self.search(*args)
type, obj = self.result(res)
if not obj:
raise NoSuchEntryError("no such entry for " + str(args))
all_users = []
for s in obj:
all_users.append(s)
return all_users
def addEntry(self,*args):
"""This wraps the add function. It assumes that the entry is already
populated with all of the desired objectclasses and attributes"""
if self.proxydn is not None:
proxydn = chr(0x04) + chr(4|0x80) + struct.pack('l', socket.htonl(len(self.proxydn))) + self.proxydn;
# Create the proxy control
sctrl=[]
sctrl.append(LDAPControl('2.16.840.1.113730.3.4.18',True,proxydn))
else:
sctrl=None
# Create the proxy control
sctrl=[]
sctrl.append(LDAPControl('2.16.840.1.113730.3.4.18',True,proxydn))
try:
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
self.add_s(*args)
except ldap.ALREADY_EXISTS:
raise ldap.ALREADY_EXISTS

View File

@ -28,6 +28,7 @@ from time import gmtime
import os
import pwd
import socket
import time
from util import *
def host_to_domain(fqdn):
@ -82,6 +83,8 @@ class KrbInstance:
self.__create_ds_keytab()
self.__create_http_keytab()
self.__create_sample_bind_zone()
self.start()
@ -175,3 +178,18 @@ class KrbInstance:
cfg_fd.close()
pent = pwd.getpwnam(self.ds_user)
os.chown("/etc/sysconfig/fedora-ds", pent.pw_uid, pent.pw_gid)
def __create_http_keytab(self):
(kwrite, kread, kerr) = os.popen3("/usr/kerberos/sbin/kadmin.local")
kwrite.write("addprinc -randkey HTTP/"+self.fqdn+"@"+self.realm+"\n")
kwrite.flush()
kwrite.write("ktadd -k /etc/httpd/conf/ipa.keytab HTTP/"+self.fqdn+"@"+self.realm+"\n")
kwrite.flush()
kwrite.close()
kread.close()
kerr.close()
while not file_exists("/etc/httpd/conf/ipa.keytab"):
time.sleep(1)
pent = pwd.getpwnam("apache")
os.chown("/etc/httpd/conf/ipa.keytab", pent.pw_uid, pent.pw_gid)

View File

@ -24,152 +24,205 @@ import ldap
import ipaserver.dsinstance
import ipaserver.ipaldap
import ipaserver.util
import pdb
import string
from types import *
import xmlrpclib
import ipa.config
# FIXME, this needs to be auto-discovered
host = 'localhost'
port = 389
binddn = "cn=directory manager"
bindpw = "freeipa"
class IPAServer:
ipa.config.init_config()
basedn = ipaserver.util.realm_to_suffix(ipa.config.config.get_realm())
import sys
sys.stderr.write(basedn)
scope = ldap.SCOPE_SUBTREE
def __init__(self):
# FIXME, this needs to be auto-discovered
self.host = 'localhost'
self.port = 636
self.bindcert = "/usr/share/ipa/cert.pem"
self.bindkey = "/usr/share/ipa/key.pem"
self.bindca = "/usr/share/ipa/cacert.asc"
def get_user (username):
"""Get a specific user's entry. Return as a dict of values.
Multi-valued fields are represented as lists.
"""
ent=""
ipa.config.init_config()
self.basedn = ipaserver.util.realm_to_suffix(ipa.config.config.get_realm())
self.scope = ldap.SCOPE_SUBTREE
self.princ = None
# FIXME: Is this the filter we want or should it be more specific?
filter = "(uid=" + username + ")"
try:
m1 = ipaserver.ipaldap.IPAdmin(host,port,binddn,bindpw)
ent = m1.getEntry(basedn, scope, filter, None)
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, e)
except ipaserver.ipaldap.NoSuchEntryError:
raise xmlrpclib.Fault(2, "No such user")
def set_principal(self, princ):
self.princ = princ
# Convert to LDIF
entry = str(ent)
def get_dn_from_principal(self, princ):
"""Given a kerberls principal get the LDAP uid"""
filter = "(krbPrincipalName=" + princ + ")"
try:
m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey)
ent = m1.getEntry(self.basedn, self.scope, filter, None)
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, e)
except ipaserver.ipaldap.NoSuchEntryError:
raise xmlrpclib.Fault(2, "No such user")
# Strip off any junk
entry = entry.strip()
return "dn:" + ent.dn
# Don't need to identify binary fields and this breaks the parser so
# remove double colons
entry = entry.replace('::', ':')
specs = [spec.split(':') for spec in entry.split('\n')]
def convert_entry(self, ent):
# Convert into a dict. We need to handle multi-valued attributes as well
# so we'll convert those into lists.
user={}
for (k,v) in specs:
k = k.lower()
if user.get(k) is not None:
if isinstance(user[k],list):
user[k].append(v.strip())
# 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('::', ':')
specs = [spec.split(':') for spec in entry.split('\n')]
# Convert into a dict. We need to handle multi-valued attributes as well
# so we'll convert those into lists.
user={}
for (k,v) in specs:
k = k.lower()
if user.get(k) is not None:
if isinstance(user[k],list):
user[k].append(v.strip())
else:
first = user[k]
user[k] = []
user[k].append(first)
user[k].append(v.strip())
else:
first = user[k]
user[k] = []
user[k].append(first)
user[k].append(v.strip())
else:
user[k] = v.strip()
user[k] = v.strip()
return user
# return str(ent) # return as LDIF
return user
def add_user (user):
"""Add a user in LDAP"""
dn="uid=%s,ou=users,ou=default,%s" % (user['uid'], basedn)
entry = ipaserver.ipaldap.Entry(dn)
def get_user (self, username, opts=None):
"""Get a specific user's entry. Return as a dict of values.
Multi-valued fields are represented as lists.
"""
ent=""
if opts:
self.set_principal(opts['remoteuser'])
if (isinstance(username, tuple)):
username = username[0]
# some required objectclasses
entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
try:
dn = 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")
# Fill in shadow fields
entry.setValue('shadowMin', '0')
entry.setValue('shadowMax', '99999')
entry.setValue('shadowWarning', '7')
entry.setValue('shadowExpire', '-1')
entry.setValue('shadowInactive', '-1')
entry.setValue('shadowFlag', '-1')
filter = "(uid=" + username + ")"
try:
m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
ent = m1.getEntry(self.basedn, self.scope, filter, None)
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, e)
except ipaserver.ipaldap.NoSuchEntryError:
raise xmlrpclib.Fault(2, "No such user")
# FIXME: calculate shadowLastChange
return self.convert_entry(ent)
# fill in our new entry with everything sent by the user
for u in user:
entry.setValues(u, user[u])
def add_user (self, user, opts=None):
"""Add a user in LDAP"""
if (isinstance(user, tuple)):
user = user[0]
dn="uid=%s,ou=users,ou=default,%s" % (user['uid'], self.basedn)
entry = ipaserver.ipaldap.Entry(str(dn))
try:
m1 = ipaserver.ipaldap.IPAdmin(host,port,binddn,bindpw)
res = m1.addEntry(entry)
return res
except ldap.ALREADY_EXISTS:
raise xmlrpclib.Fault(3, "User already exists")
return None
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, str(e))
return None
# some required objectclasses
entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
def get_add_schema ():
"""Get the list of fields to be used when adding users in the GUI."""
# Fill in shadow fields
entry.setValue('shadowMin', '0')
entry.setValue('shadowMax', '99999')
entry.setValue('shadowWarning', '7')
entry.setValue('shadowExpire', '-1')
entry.setValue('shadowInactive', '-1')
entry.setValue('shadowFlag', '-1')
# FIXME: this needs to be pulled from LDAP
fields = []
# FIXME: calculate shadowLastChange
field1 = {
"name": "uid" ,
"label": "Login:",
"type": "text",
"validator": "text",
"required": "true"
}
fields.append(field1)
# fill in our new entry with everything sent by the user
for u in user:
entry.setValues(str(u), str(user[u]))
field1 = {
"name": "userPassword" ,
"label": "Password:",
"type": "password",
"validator": "String",
"required": "true"
}
fields.append(field1)
if opts:
self.set_principal(opts['remoteuser'])
field1 = {
"name": "givenName" ,
"label": "First name:",
"type": "text",
"validator": "string",
"required": "true"
}
fields.append(field1)
try:
dn = 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")
field1 = {
"name": "sn" ,
"label": "Last name:",
"type": "text",
"validator": "string",
"required": "true"
}
fields.append(field1)
try:
m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
res = m1.addEntry(entry)
return res
except ldap.ALREADY_EXISTS:
raise xmlrpclib.Fault(3, "User already exists")
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, str(e))
field1 = {
"name": "mail" ,
"label": "E-mail address:",
"type": "text",
"validator": "email",
"required": "true"
}
fields.append(field1)
def get_add_schema (self):
"""Get the list of fields to be used when adding users in the GUI."""
return fields
# FIXME: this needs to be pulled from LDAP
fields = []
field1 = {
"name": "uid" ,
"label": "Login:",
"type": "text",
"validator": "text",
"required": "true"
}
fields.append(field1)
field1 = {
"name": "givenName" ,
"label": "First name:",
"type": "text",
"validator": "string",
"required": "true"
}
fields.append(field1)
field1 = {
"name": "sn" ,
"label": "Last name:",
"type": "text",
"validator": "string",
"required": "true"
}
fields.append(field1)
field1 = {
"name": "mail" ,
"label": "E-mail address:",
"type": "text",
"validator": "email",
"required": "true"
}
fields.append(field1)
return fields
def get_all_users (self):
"""Return a list containing a User object for each
existing user.
"""
# FIXME: Is this the filter we want or should it be more specific?
filter = "(objectclass=posixAccount)"
try:
m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey)
all_users = m1.getList(self.basedn, self.scope, filter, None)
except ldap.LDAPError, e:
raise xmlrpclib.Fault(1, e)
except ipaserver.ipaldap.NoSuchEntryError:
raise xmlrpclib.Fault(2, "No such user")
users = []
for u in all_users:
users.append(self.convert_entry(u))
return users

View File

@ -3,15 +3,15 @@
Alias /ipa "/usr/share/ipa/ipaserver/XMLRPC"
<Directory "/usr/share/ipa/ipaserver">
# AuthType Kerberos
# AuthName "Kerberos Login"
# KrbMethodNegotiate on
# KrbMethodK5Passwd off
# KrbServiceName HTTP
# KrbAuthRealms GREYOAK.COM
# Krb5KeyTab /etc/httpd/conf/ipa.keytab
# KrbSaveCredentials on
# Require valid-user
AuthType Kerberos
AuthName "Kerberos Login"
KrbMethodNegotiate on
KrbMethodK5Passwd off
KrbServiceName HTTP
KrbAuthRealms GREYOAK.COM
Krb5KeyTab /etc/httpd/conf/ipa.keytab
KrbSaveCredentials on
Require valid-user
ErrorDocument 401 /errors/unauthorized.html
SetHandler mod_python

View File

@ -123,11 +123,16 @@ class ModXMLRPCRequestHandler(object):
def register_instance(self,instance):
self.register_module(instance)
def _marshaled_dispatch(self, data):
def _marshaled_dispatch(self, data, remoteuser):
"""Dispatches an XML-RPC method from marshalled (XML) data."""
params, method = loads(data)
opts={}
opts['remoteuser'] = remoteuser
params = ipaserver.encode_args(params, opts)
# special case
# if method == "get_user":
# Marshaller._Marshaller__dump = xmlrpclib_dump
@ -239,7 +244,7 @@ class ModXMLRPCRequestHandler(object):
req.allow_methods(['POST'],1)
raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED
response = self._marshaled_dispatch(req.read())
response = self._marshaled_dispatch(req.read(), req.user)
req.content_type = "text/xml"
req.set_content_length(len(response))
@ -267,10 +272,12 @@ def handler(req, profiling=False):
else:
opts = req.get_options()
try:
f = funcs.IPAServer()
h = ModXMLRPCRequestHandler()
h.register_function(funcs.get_user)
h.register_function(funcs.add_user)
h.register_function(funcs.get_add_schema)
h.register_function(f.get_user)
h.register_function(f.add_user)
h.register_function(f.get_add_schema)
h.register_function(f.get_all_users)
h.handle_request(req)
finally:
pass