summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/b_xmlrpc.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib/plugins/b_xmlrpc.py')
-rw-r--r--ipalib/plugins/b_xmlrpc.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/ipalib/plugins/b_xmlrpc.py b/ipalib/plugins/b_xmlrpc.py
new file mode 100644
index 00000000..14f2a9be
--- /dev/null
+++ b/ipalib/plugins/b_xmlrpc.py
@@ -0,0 +1,102 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+# Rob Crittenden <rcritten@redhat.com>
+#
+# Copyright (C) 2008 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 only
+#
+# 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
+
+"""
+Backend plugin for XML-RPC client.
+
+This provides a lightwieght XML-RPC client using Python standard library
+``xmlrpclib`` module.
+"""
+
+import xmlrpclib
+import socket
+import httplib
+import kerberos
+from ipalib.backend import Backend
+from ipalib.util import xmlrpc_marshal
+from ipalib import api
+from ipalib import errors
+
+class xmlrpc(Backend):
+ """
+ XML-RPC client backend plugin.
+ """
+
+ def get_client(self):
+ """
+ Return an xmlrpclib.ServerProxy instance (the client).
+ """
+ # FIXME: Rob, is there any reason we can't use allow_none=True here?
+ # Are there any reasonably common XML-RPC client implementations
+ # that don't support the <nil/> extension?
+ # See: http://docs.python.org/library/xmlrpclib.html
+ uri = self.env.xmlrpc_uri
+ if uri.startswith('https://'):
+ return xmlrpclib.ServerProxy(uri,
+ transport=KerbTransport(),
+ )
+ return xmlrpclib.ServerProxy(uri)
+
+ def forward_call(self, name, *args, **kw):
+ """
+ Forward a call over XML-RPC to an IPA server.
+ """
+ self.info('Forwarding %r call to %r' % (name, self.env.xmlrpc_uri))
+ client = self.get_client()
+ command = getattr(client, name)
+ params = xmlrpc_marshal(*args, **kw)
+ try:
+ return command(*params)
+ except socket.error, e:
+ raise
+ except xmlrpclib.Fault, e:
+ err = errors.convertFault(e)
+ raise err
+ return
+
+api.register(xmlrpc)
+
+class KerbTransport(xmlrpclib.SafeTransport):
+ """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 kerberos.GSSError(e)
+
+ try:
+ kerberos.authGSSClientStep(vc, "");
+ except kerberos.GSSError, e:
+ raise kerberos.GSSError(e)
+
+ extra_headers = [
+ ("Authorization", "negotiate %s" % kerberos.authGSSClientResponse(vc) )
+ ]
+
+ return host, extra_headers, x509