summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2007-08-09 14:52:54 -0400
committerSimo Sorce <ssorce@redhat.com>2007-08-09 14:52:54 -0400
commita59c36b394dba5f8b371c1a6cdab0317a5507486 (patch)
tree91cbc96560da1e0aebe3b0dda64c8b3191495a0b
parent950bddf2a32b765ee97df5442a1ec9c0a358ccb3 (diff)
parentcf93b1bc642a843242cc9aaf585c08c5475ad632 (diff)
downloadfreeipa.git-a59c36b394dba5f8b371c1a6cdab0317a5507486.tar.gz
freeipa.git-a59c36b394dba5f8b371c1a6cdab0317a5507486.tar.xz
freeipa.git-a59c36b394dba5f8b371c1a6cdab0317a5507486.zip
merge in changes from upstream
-rw-r--r--Makefile19
-rwxr-xr-xipa-admintools/freeipa-admintools.spec11
-rwxr-xr-xipa-admintools/freeipa-admintools.spec.in11
-rw-r--r--ipa-admintools/ipa-adduser25
-rw-r--r--ipa-admintools/ipa-finduser40
-rw-r--r--ipa-python/Makefile8
-rw-r--r--ipa-python/config.py106
-rwxr-xr-xipa-python/freeipa-python.spec12
-rwxr-xr-xipa-python/freeipa-python.spec.in12
-rw-r--r--ipa-python/ipa.conf3
-rw-r--r--ipa-python/ipaclient.py87
-rw-r--r--ipa-python/krbtransport.py55
-rw-r--r--ipa-python/rpcclient.py146
-rw-r--r--ipa-python/user.py112
-rwxr-xr-xipa-server/freeipa-server.spec18
-rw-r--r--ipa-server/freeipa-server.spec.in18
-rw-r--r--ipa-server/ipa-install/Makefile3
-rw-r--r--ipa-server/ipa-install/ipa-server-install12
-rw-r--r--ipa-server/ipa-install/ipa-server-setupssl68
-rw-r--r--ipa-server/ipa-install/share/bootstrap-template.ldif23
-rw-r--r--ipa-server/ipa-install/share/certmap.conf.template82
-rw-r--r--ipa-server/ipa-install/share/default-aci.ldif4
-rw-r--r--ipa-server/ipa-install/test/Makefile8
-rw-r--r--ipa-server/ipa-install/test/test-users-template.ldif (renamed from ipa-server/ipa-install/test/test-users.ldif)12
-rw-r--r--ipa-server/ipaserver/dsinstance.py22
-rw-r--r--ipa-server/ipaserver/ipaldap.py77
-rw-r--r--ipa-server/ipaserver/krbinstance.py28
-rw-r--r--ipa-server/xmlrpc-server/Makefile3
-rw-r--r--ipa-server/xmlrpc-server/funcs.py340
-rw-r--r--ipa-server/xmlrpc-server/ipa.conf18
-rw-r--r--ipa-server/xmlrpc-server/ipaxmlrpc.py17
31 files changed, 1054 insertions, 346 deletions
diff --git a/Makefile b/Makefile
index 350bf9bc..5de0c5d3 100644
--- a/Makefile
+++ b/Makefile
@@ -53,10 +53,20 @@ version-update:
> ipa-python/freeipa-python.spec
-tarballs:
+archive:
-mkdir -p dist
hg archive -t files dist/freeipa
+local-archive:
+ -mkdir -p dist/freeipa
+ @for subdir in $(SUBDIRS); do \
+ cp -pr $$subdir dist/freeipa/.; \
+ done
+
+archive-cleanup:
+ rm -fr dist/freeipa
+
+tarballs:
# ipa-server
mv dist/freeipa/ipa-server dist/$(SERV_TARBALL_PREFIX)
rm -f dist/$(SERV_TARBALL)
@@ -75,9 +85,6 @@ tarballs:
cd dist; tar cfz $(PYTHON_TARBALL) $(PYTHON_TARBALL_PREFIX)
rm -fr dist/$(PYTHON_TARBALL_PREFIX)
- # cleanup
- rm -fr dist/freeipa
-
rpm-ipa-server:
cp dist/$(SERV_TARBALL) ~/rpmbuild/SOURCES/.
rpmbuild -ba ipa-server/freeipa-server.spec
@@ -98,7 +105,9 @@ rpm-ipa-python:
rpms: rpm-ipa-server rpm-ipa-admin rpm-ipa-python
-dist: version-update tarballs rpms
+dist: version-update archive tarballs archive-cleanup rpms
+
+local-dist: clean version-update local-archive tarballs archive-cleanup rpms
dist-clean: clean
rm -fr dist
diff --git a/ipa-admintools/freeipa-admintools.spec b/ipa-admintools/freeipa-admintools.spec
index bcd3d9d2..904a3b69 100755
--- a/ipa-admintools/freeipa-admintools.spec
+++ b/ipa-admintools/freeipa-admintools.spec
@@ -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
-* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
-- Initial rpm version
+* 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
diff --git a/ipa-admintools/freeipa-admintools.spec.in b/ipa-admintools/freeipa-admintools.spec.in
index bcd3d9d2..904a3b69 100755
--- a/ipa-admintools/freeipa-admintools.spec.in
+++ b/ipa-admintools/freeipa-admintools.spec.in
@@ -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
-* Fri Jul 27 2007 Karl MacMillan <kmacmill@localhost.localdomain> - 0.1.0-1
-- Initial rpm version
+* 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
diff --git a/ipa-admintools/ipa-adduser b/ipa-admintools/ipa-adduser
index b40fdee2..af922833 100644
--- a/ipa-admintools/ipa-adduser
+++ b/ipa-admintools/ipa-adduser
@@ -21,8 +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"
@@ -43,7 +46,8 @@ def parse_options():
parser.add_option("--usage", action="store_true",
help="Program usage")
- (options, args) = parser.parse_args()
+ args = ipa.config.init_config(sys.argv)
+ options, args = parser.parse_args(args)
if not options.gn or not options.sn:
usage()
@@ -52,14 +56,14 @@ def parse_options():
def main():
user={}
- (options, args) = parse_options()
+ options, args = parse_options()
- if len(args) != 1:
+ if len(args) != 2:
usage()
- user['gn'] = options.gn
+ user['givenName'] = options.gn
user['sn'] = options.sn
- user['uid'] = args[0]
+ user['uid'] = args[1]
if options.gecos:
user['gecos'] = options.gecos
if options.directory:
@@ -70,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
diff --git a/ipa-admintools/ipa-finduser b/ipa-admintools/ipa-finduser
index 205b47ce..a54e141e 100644
--- a/ipa-admintools/ipa-finduser
+++ b/ipa-admintools/ipa-finduser
@@ -18,12 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+import sys
from optparse import OptionParser
-import ipa
-import ipa.rpcclient
-import base64
+import ipa.ipaclient as ipaclient
+import ipa.config
+
import sys
import xmlrpclib
+import kerberos
def usage():
print "ipa-finduser <uid>"
@@ -32,28 +34,40 @@ def usage():
def parse_options():
parser = OptionParser()
- (options, args) = parser.parse_args()
+ args = ipa.config.init_config(sys.argv)
+ options, args = parser.parse_args(args)
return options, args
def main():
user={}
- (options, args) = parse_options()
+ options, args = parse_options()
- if len(args) != 1:
+ if len(args) != 2:
usage()
try:
- ent = ipa.rpcclient.get_user(args[0])
- 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
diff --git a/ipa-python/Makefile b/ipa-python/Makefile
index bc6554be..b2e4660f 100644
--- a/ipa-python/Makefile
+++ b/ipa-python/Makefile
@@ -1,11 +1,17 @@
PYTHONLIBDIR ?= $(shell python -c "from distutils.sysconfig import *; print get_python_lib(1)")
PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/ipa
+CONFIGDIR ?= $(DESTDIR)/etc/ipa
all: ;
install:
-mkdir -p $(PACKAGEDIR)
install -m 644 *.py $(PACKAGEDIR)
+ -mkdir -p $(CONFIGDIR)
+ if ! [ -e $(CONFIGDIR)/ipa.conf ]; then \
+ install -m 644 ipa.conf $(CONFIGDIR); \
+ fi
clean:
- rm -f *~ *.pyc \ No newline at end of file
+ rm -f *~ *.pyc
+
diff --git a/ipa-python/config.py b/ipa-python/config.py
new file mode 100644
index 00000000..a17e585b
--- /dev/null
+++ b/ipa-python/config.py
@@ -0,0 +1,106 @@
+# Authors: Karl MacMillan <kmacmill@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
+#
+
+import ConfigParser
+from optparse import OptionParser
+
+class IPAConfigError(Exception):
+ def __init__(self, msg=''):
+ self.msg = msg
+ Exception.__init__(self, msg)
+
+ def __repr__(self):
+ return self.msg
+
+ __str__ = __repr__
+
+class IPAConfig:
+ def __init__(self):
+ self.default_realm = None
+ self.default_server = None
+
+ def get_realm(self):
+ if self.default_realm:
+ return self.default_realm
+ else:
+ raise IPAConfigError("no default realm")
+
+ def get_server(self):
+ if self.default_server:
+ return self.default_server
+ else:
+ raise IPAConfigError("no default server")
+
+# Global library config
+config = IPAConfig()
+
+def __parse_config():
+ p = ConfigParser.SafeConfigParser()
+ p.read("/etc/ipa/ipa.conf")
+
+ try:
+ config.default_realm = p.get("defaults", "realm")
+ config.default_server = p.get("defaults", "server")
+ except:
+ pass
+
+def usage():
+ return """ --realm\tset the IPA realm
+ --server\tset the IPA server
+"""
+
+def __parse_args(args):
+ # Can't use option parser because it doesn't easily leave
+ # unknown arguments - creating our own seems simpler.
+ #
+ # should make this more robust and handle --realm=foo syntax
+ out_args = []
+ i = 0
+ while i < len(args):
+ if args[i] == "--realm":
+ if i == len(args) - 1:
+ raise IPAConfigError("missing argument to --realm")
+ config.default_realm = args[i + 1]
+ i = i + 2
+ continue
+ if args[i] == "--server":
+ if i == len(args) - 1:
+ raise IPAConfigError("missing argument to --server")
+ config.default_server = args[i + 1]
+ i = i + 2
+ continue
+ out_args.append(args[i])
+ i = i + 1
+
+ return out_args
+
+
+def init_config(args=None):
+ __parse_config()
+ out_args = None
+ if args:
+ out_args = __parse_args(args)
+
+ if not config.default_realm:
+ raise IPAConfigError("realm not specified in config file or on command line")
+ if not config.default_server:
+ raise IPAConfigError("server not specified in config file or on command line")
+
+ if out_args:
+ return out_args
diff --git a/ipa-python/freeipa-python.spec b/ipa-python/freeipa-python.spec
index 61be3a5d..e9b1e708 100755
--- a/ipa-python/freeipa-python.spec
+++ b/ipa-python/freeipa-python.spec
@@ -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
@@ -15,6 +15,7 @@ Requires: python
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
%define pkgpythondir %{python_sitelib}/ipa
+%define configdir /etc/ipa
%description
FreeIPA is a server for identity, policy, and audit.
@@ -25,6 +26,7 @@ FreeIPA is a server for identity, policy, and audit.
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{pkgpythondir}
+mkdir -p %{buildroot}%{configdir}
make install DESTDIR=%{buildroot}
@@ -36,9 +38,17 @@ rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{pkgpythondir}/*
+%config(noreplace) %{configdir}/ipa.conf
%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
diff --git a/ipa-python/freeipa-python.spec.in b/ipa-python/freeipa-python.spec.in
index 90a135b4..b0a37308 100755
--- a/ipa-python/freeipa-python.spec.in
+++ b/ipa-python/freeipa-python.spec.in
@@ -1,6 +1,6 @@
Name: freeipa-python
Version: VERSION
-Release: 1%{?dist}
+Release: 3%{?dist}
Summary: FreeIPA authentication server
Group: System Environment/Base
@@ -15,6 +15,7 @@ Requires: python
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
%define pkgpythondir %{python_sitelib}/ipa
+%define configdir /etc/ipa
%description
FreeIPA is a server for identity, policy, and audit.
@@ -25,6 +26,7 @@ FreeIPA is a server for identity, policy, and audit.
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{pkgpythondir}
+mkdir -p %{buildroot}%{configdir}
make install DESTDIR=%{buildroot}
@@ -36,9 +38,17 @@ rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{pkgpythondir}/*
+%config(noreplace) %{configdir}/ipa.conf
%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
diff --git a/ipa-python/ipa.conf b/ipa-python/ipa.conf
new file mode 100644
index 00000000..5243cf22
--- /dev/null
+++ b/ipa-python/ipa.conf
@@ -0,0 +1,3 @@
+[defaults]
+realm = foo.bar
+server = realm.foo.bar
diff --git a/ipa-python/ipaclient.py b/ipa-python/ipaclient.py
new file mode 100644
index 00000000..c75b5bc9
--- /dev/null
+++ b/ipa-python/ipaclient.py
@@ -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
diff --git a/ipa-python/krbtransport.py b/ipa-python/krbtransport.py
new file mode 100644
index 00000000..dbb8ec34
--- /dev/null
+++ b/ipa-python/krbtransport.py
@@ -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
+
diff --git a/ipa-python/rpcclient.py b/ipa-python/rpcclient.py
index 41602662..d4e645e1 100644
--- a/ipa-python/rpcclient.py
+++ b/ipa-python/rpcclient.py
@@ -20,83 +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
+
+class RPCClient:
+
+ def __init__(self):
+ ipa.config.init_config()
-# FIXME: do we want this set somewhere else?
-server = xmlrpclib.ServerProxy("http://localhost:80/ipa")
-
-def get_user(username):
- """Get a specific user"""
+ def server_url(self):
+ return "http://" + config.config.get_server() + "/ipa"
- 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 setup_server(self):
+ return xmlrpclib.ServerProxy(self.server_url(), KerbTransport())
- return myuser
+ 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]
-def add_user(user):
- """Add a new user"""
-
- # FIXME: Get the realm from somewhere
- realm="GREYOAK.COM"
-
- # 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'
+ return user
+
+ 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: What is the default group for users?
- user['gidNumber'] ='501'
- user['krbPrincipalName'] = "%s@%s" % (user['uid'], realm)
- user['cn'] = "%s %s" % (user['gn'], user['sn'])
- if user.get('gn'):
- del user['gn']
+ return result
+
+
+ def add_user(self,user):
+ """Add a new user"""
+ server = self.setup_server()
+
+ 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)
- 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(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_add_schema():
- """Get the list of attributes we need to ask when adding a new
- user.
- """
+ def get_all_users (self):
+ """Return a list containing a User object for each existing user."""
- # 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)
- return None
- except socket.error, (value, msg):
- raise xmlrpclib.Fault(value, msg)
- return None
-
- return result
+ 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
diff --git a/ipa-python/user.py b/ipa-python/user.py
new file mode 100644
index 00000000..6162354b
--- /dev/null
+++ b/ipa-python/user.py
@@ -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()
diff --git a/ipa-server/freeipa-server.spec b/ipa-server/freeipa-server.spec
index 4801eb7f..463db589 100755
--- a/ipa-server/freeipa-server.spec
+++ b/ipa-server/freeipa-server.spec
@@ -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 ntpd cyrus-sasl-gssapi
%define httpd_conf /etc/httpd/conf.d
@@ -23,7 +23,6 @@ FreeIPA is a server for identity, policy, and audit.
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{_sbindir}
-mkdir -p %{buildroot}%{httpd_conf}
make install DESTDIR=%{buildroot}
@@ -40,10 +39,19 @@ rm -rf %{buildroot}
%dir %{_usr}/share/ipa
%{_usr}/share/ipa/*
-%{httpd_conf}/ipa.conf
-
%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
diff --git a/ipa-server/freeipa-server.spec.in b/ipa-server/freeipa-server.spec.in
index 16aff06b..549afc97 100644
--- a/ipa-server/freeipa-server.spec.in
+++ b/ipa-server/freeipa-server.spec.in
@@ -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 ntpd cyrus-sasl-gssapi
%define httpd_conf /etc/httpd/conf.d
@@ -23,7 +23,6 @@ FreeIPA is a server for identity, policy, and audit.
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{_sbindir}
-mkdir -p %{buildroot}%{httpd_conf}
make install DESTDIR=%{buildroot}
@@ -40,10 +39,19 @@ rm -rf %{buildroot}
%dir %{_usr}/share/ipa
%{_usr}/share/ipa/*
-%{httpd_conf}/ipa.conf
-
%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
diff --git a/ipa-server/ipa-install/Makefile b/ipa-server/ipa-install/Makefile
index 0d495397..877ae09c 100644
--- a/ipa-server/ipa-install/Makefile
+++ b/ipa-server/ipa-install/Makefile
@@ -6,7 +6,8 @@ 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 $@
- rm -f *~ *.pyc \ No newline at end of file
+ rm -f *~ *.pyc
diff --git a/ipa-server/ipa-install/ipa-server-install b/ipa-server/ipa-install/ipa-server-install
index 7abcafd8..2fa9182b 100644
--- a/ipa-server/ipa-install/ipa-server-install
+++ b/ipa-server/ipa-install/ipa-server-install
@@ -75,7 +75,7 @@ def logging_setup(options):
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
-
+
def main():
options = parse_options()
logging_setup(options)
@@ -119,6 +119,16 @@ 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")
+ fd.write("server=" + host_name + "\n")
+ fd.write("realm=" + options.realm_name + "\n")
+ fd.close()
+
return 0
main()
diff --git a/ipa-server/ipa-install/ipa-server-setupssl b/ipa-server/ipa-install/ipa-server-setupssl
index f7532790..d7eb6f39 100644
--- a/ipa-server/ipa-install/ipa-server-setupssl
+++ b/ipa-server/ipa-install/ipa-server-setupssl
@@ -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
diff --git a/ipa-server/ipa-install/share/bootstrap-template.ldif b/ipa-server/ipa-install/share/bootstrap-template.ldif
index d83f715b..444a29d4 100644
--- a/ipa-server/ipa-install/share/bootstrap-template.ldif
+++ b/ipa-server/ipa-install/share/bootstrap-template.ldif
@@ -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
diff --git a/ipa-server/ipa-install/share/certmap.conf.template b/ipa-server/ipa-install/share/certmap.conf.template
new file mode 100644
index 00000000..676d3ef3
--- /dev/null
+++ b/ipa-server/ipa-install/share/certmap.conf.template
@@ -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
diff --git a/ipa-server/ipa-install/share/default-aci.ldif b/ipa-server/ipa-install/share/default-aci.ldif
index 8916833c..a32729a3 100644
--- a/ipa-server/ipa-install/share/default-aci.ldif
+++ b/ipa-server/ipa-install/share/default-aci.ldif
@@ -7,4 +7,6 @@ aci: (targetattr="carLicense ||description ||displayName ||facsimileTelephoneNum
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: (targetattr="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTPassword")(version 3.0; acl "Kpasswd access to passowrd hashes for passowrd changes"; allow (all) userdn="ldap:///krbprincipalname=kadmin/changepw@$REALM,cn=$REALM,cn=kerberos,$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";)
diff --git a/ipa-server/ipa-install/test/Makefile b/ipa-server/ipa-install/test/Makefile
new file mode 100644
index 00000000..696ae771
--- /dev/null
+++ b/ipa-server/ipa-install/test/Makefile
@@ -0,0 +1,8 @@
+SHAREDIR = $(DESTDIR)/usr/share/ipa
+
+install:
+ -mkdir -p $(SHAREDIR)
+ install -m 644 *.ldif $(SHAREDIR)
+
+clean:
+ rm -f *~
diff --git a/ipa-server/ipa-install/test/test-users.ldif b/ipa-server/ipa-install/test/test-users-template.ldif
index 424eedb5..0057d976 100644
--- a/ipa-server/ipa-install/test/test-users.ldif
+++ b/ipa-server/ipa-install/test/test-users-template.ldif
@@ -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
diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py
index 775a2f2b..face142a 100644
--- a/ipa-server/ipaserver/dsinstance.py
+++ b/ipa-server/ipaserver/dsinstance.py
@@ -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")
diff --git a/ipa-server/ipaserver/ipaldap.py b/ipa-server/ipaserver/ipaldap.py
index f440ae4b..ee0388ca 100644
--- a/ipa-server/ipaserver/ipaldap.py
+++ b/ipa-server/ipaserver/ipaldap.py
@@ -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()
-
- def __init__(self,host,port,binddn,bindpw):
+ SimpleLDAPObject.__init__(self,'ldaps://%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"""
+# 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
diff --git a/ipa-server/ipaserver/krbinstance.py b/ipa-server/ipaserver/krbinstance.py
index 9d9d69be..df403471 100644
--- a/ipa-server/ipaserver/krbinstance.py
+++ b/ipa-server/ipaserver/krbinstance.py
@@ -28,6 +28,7 @@ from time import gmtime
import os
import pwd
import socket
+import time
from util import *
def host_to_domain(fqdn):
@@ -78,10 +79,16 @@ class KrbInstance:
self.__configure_ldap()
+ self.__configure_http()
+
self.__create_instance()
self.__create_ds_keytab()
+ self.__create_http_keytab()
+
+ self.__set_kadmin_changepw_preauth()
+
self.__create_sample_bind_zone()
self.start()
@@ -183,3 +190,24 @@ class KrbInstance:
kwrite.close()
kread.close()
kerr.close()
+
+ 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)
+
+ def __configure_http(self):
+ http_txt = template_file(SHARE_DIR + "ipa.conf", self.sub_dict)
+ http_fd = open("/etc/httpd/conf.d/ipa.conf", "w")
+ http_fd.write(http_txt)
+ http_fd.close()
diff --git a/ipa-server/xmlrpc-server/Makefile b/ipa-server/xmlrpc-server/Makefile
index 10b796ea..7d219a7b 100644
--- a/ipa-server/xmlrpc-server/Makefile
+++ b/ipa-server/xmlrpc-server/Makefile
@@ -1,12 +1,11 @@
SHAREDIR = $(DESTDIR)/usr/share/ipa/ipaserver
-HTTPDIR = $(DESTDIR)/etc/httpd/conf.d/
all: ;
install:
-mkdir -p $(SHAREDIR)
install -m 644 *.py $(SHAREDIR)
- install -m 644 ipa.conf $(HTTPDIR)
+ install -m 644 ipa.conf $(SHAREDIR)/..
clean:
rm -f *~ *.pyc
diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py
index d6473f9a..9545ad89 100644
--- a/ipa-server/xmlrpc-server/funcs.py
+++ b/ipa-server/xmlrpc-server/funcs.py
@@ -23,148 +23,206 @@ sys.path.append("/usr/share/ipa")
import ldap
import ipaserver.dsinstance
import ipaserver.ipaldap
-import pdb
+import ipaserver.util
import string
from types import *
import xmlrpclib
-
-# FIXME, this needs to be auto-discovered
-host = 'localhost'
-port = 389
-binddn = "cn=directory manager"
-bindpw = "freeipa"
-
-basedn = "dc=greyoak,dc=com"
-scope = ldap.SCOPE_SUBTREE
-
-def get_user (username):
- """Get a specific user's entry. Return as a dict of values.
- Multi-valued fields are represented as lists.
- """
- ent=""
-
- # 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")
-
- # 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())
+import ipa.config
+
+class IPAServer:
+
+ 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"
+
+ ipa.config.init_config()
+ self.basedn = ipaserver.util.realm_to_suffix(ipa.config.config.get_realm())
+ self.scope = ldap.SCOPE_SUBTREE
+ self.princ = None
+
+ def set_principal(self, princ):
+ self.princ = princ
+
+ 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")
+
+ return "dn:" + ent.dn
+
+ def convert_entry(self, ent):
+
+ # 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()
-
- return user
-# return str(ent) # return as LDIF
-
-def add_user (user):
- """Add a user in LDAP"""
- dn="uid=%s,ou=users,ou=default,dc=greyoak,dc=com" % user['uid']
- entry = ipaserver.ipaldap.Entry(dn)
-
- # some required objectclasses
- entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
-
- # 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: calculate shadowLastChange
-
- # fill in our new entry with everything sent by the user
- for u in user:
- entry.setValues(u, user[u])
-
- 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
-
-def get_add_schema ():
- """Get the list of fields to be used when adding users in the GUI."""
-
- # 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": "userPassword" ,
- "label": "Password:",
- "type": "password",
- "validator": "String",
- "required": "true"
- }
- fields.append(field1)
-
- field1 = {
- "name": "gn" ,
- "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
+ user[k] = v.strip()
+
+ return user
+
+ 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]
+
+ 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")
+
+ 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")
+
+ return self.convert_entry(ent)
+
+ 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))
+
+ # some required objectclasses
+ entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
+
+ # 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: calculate shadowLastChange
+
+ # fill in our new entry with everything sent by the user
+ for u in user:
+ entry.setValues(str(u), str(user[u]))
+
+ if opts:
+ self.set_principal(opts['remoteuser'])
+
+ 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")
+
+ 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))
+
+ def get_add_schema (self):
+ """Get the list of fields to be used when adding users in the GUI."""
+
+ # 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
diff --git a/ipa-server/xmlrpc-server/ipa.conf b/ipa-server/xmlrpc-server/ipa.conf
index 1880268c..b80c5c57 100644
--- a/ipa-server/xmlrpc-server/ipa.conf
+++ b/ipa-server/xmlrpc-server/ipa.conf
@@ -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 $REALM
+ Krb5KeyTab /etc/httpd/conf/ipa.keytab
+ KrbSaveCredentials on
+ Require valid-user
ErrorDocument 401 /errors/unauthorized.html
SetHandler mod_python
diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py
index ad5e3068..7bad9ab5 100644
--- a/ipa-server/xmlrpc-server/ipaxmlrpc.py
+++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py
@@ -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