summaryrefslogtreecommitdiffstats
path: root/ipaserver/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/plugins')
-rw-r--r--ipaserver/plugins/dogtag.py (renamed from ipaserver/plugins/ra.py)50
-rw-r--r--ipaserver/plugins/rabase.py113
-rw-r--r--ipaserver/plugins/selfsign.py126
3 files changed, 253 insertions, 36 deletions
diff --git a/ipaserver/plugins/ra.py b/ipaserver/plugins/dogtag.py
index 1238f5036..2b1e84e7a 100644
--- a/ipaserver/plugins/ra.py
+++ b/ipaserver/plugins/dogtag.py
@@ -20,39 +20,22 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-Backend plugin for IPA-RA.
-
-The `ra` plugin provides access to the CA to issue, retrieve, and revoke
-certificates via the following methods:
-
- * `ra.check_request_status()` - check certificate request status.
- * `ra.get_certificate()` - retrieve an existing certificate.
- * `ra.request_certificate()` - request a new certificate.
- * `ra.revoke_certificate()` - revoke a certificate.
- * `ra.take_certificate_off_hold()` - take a certificate off hold.
+Backend plugin for RA using Dogtag.
"""
from ipalib import api, SkipPluginModule
-if api.env.enable_ra is not True:
+if api.env.ra_plugin != 'dogtag':
# In this case, abort loading this plugin module...
- raise SkipPluginModule(reason='env.enable_ra is not True')
-import os, stat, subprocess
-import array
-import errno
-import binascii
+ raise SkipPluginModule(reason='dogtag not selected as RA plugin')
+import os
from httplib import HTTPConnection
-from urllib import urlencode, quote
-from socket import gethostname
+from urllib import urlencode
+from ipaserver.plugins import rabase
import socket
-from ipalib import Backend
from ipalib.errors import NetworkError
-from ipaserver import servercore
-from ipaserver import ipaldap
from ipalib.constants import TYPE_ERROR
from ipapython import nsslib
import nss.nss as nss
-import nss.ssl as ssl
-from nss.error import NSPRError
import xml.dom.minidom
def get_xml_value(doc, tagname):
@@ -62,7 +45,7 @@ def get_xml_value(doc, tagname):
except IndexError:
return None
-class ra(Backend):
+class ra(rabase.rabase):
"""
Request Authority backend plugin.
"""
@@ -110,29 +93,20 @@ class ra(Backend):
self.debug('request data %s', data)
return (status, reason, data)
- def _sslget(self, url, **kw):
+ def _sslget(self, url, port, **kw):
"""
Perform an HTTPS request
:param url: The URL to post to.
:param kw: Keyword arguments to encode into POST body.
"""
- uri = 'https://%s:%d%s' % (self.env.ca_host, self.env.ca_ssl_port, url)
+ uri = 'https://%s:%d%s' % (self.env.ca_host, port, url)
post = urlencode(kw)
self.info('sslget %r', uri)
self.debug('sslget post %r', post)
- argv = [
- '/usr/bin/sslget',
- '-n', self.ipa_certificate_nickname, # nickname
- '-w', self.pwd_file, # pwfile
- '-d', self.sec_dir, # dbdir
- '-e', post, # post
- '-r', url, # url
- '%s:%d' % (self.env.ca_host, self.env.ca_ssl_port),
- ]
headers = {"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}
- conn = nsslib.NSSConnection(self.env.ca_host, self.env.ca_ssl_port, dbdir=self.sec_dir)
+ conn = nsslib.NSSConnection(self.env.ca_host, port, dbdir=self.sec_dir)
conn.sslsock.set_client_auth_data_callback(nsslib.client_auth_data_callback, self.ipa_certificate_nickname, self.password, nss.get_default_certdb())
conn.set_debuglevel(10)
conn.request("POST", url, post, headers)
@@ -194,6 +168,7 @@ class ra(Backend):
issued_certificate = None
(status, reason, stdout) = self._sslget(
'/ca/agent/ca/displayBySerial',
+ self.env.ca_agent_port,
serialNumber=serial_number,
xmlOutput='true',
)
@@ -229,6 +204,7 @@ class ra(Backend):
self.debug('%s.request_certificate()', self.fullname)
certificate = None
(status, reason, stdout) = self._sslget('/ca/ee/ca/profileSubmit',
+ self.env.ca_ee_port,
profileId='caRAserverCert',
cert_request_type=request_type,
cert_request=csr,
@@ -292,6 +268,7 @@ class ra(Backend):
)
response = {}
(status, reason, stdout) = self._sslget('/ca/agent/ca/doRevoke',
+ self.env.ca_agent_port,
op='revoke',
revocationReason=revocation_reason,
revokeAll='(certRecordId=%s)' % serial_number,
@@ -316,6 +293,7 @@ class ra(Backend):
response = {}
self.debug('%s.take_certificate_off_hold()', self.fullname)
(status, reason, stdout) = self._sslget('/ca/agent/ca/doUnrevoke',
+ self.env.ca_agent_port,
serialNumber=serial_number,
)
if (status == 0):
diff --git a/ipaserver/plugins/rabase.py b/ipaserver/plugins/rabase.py
new file mode 100644
index 000000000..3fc0ec5cd
--- /dev/null
+++ b/ipaserver/plugins/rabase.py
@@ -0,0 +1,113 @@
+# Authors:
+# Rob Crittenden <rcritten@@redhat.com>
+#
+# Copyright (C) 2009 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 RA activities.
+
+The `ra` plugin provides access to the CA to issue, retrieve, and revoke
+certificates via the following methods:
+
+ * `ra.check_request_status()` - check certificate request status.
+ * `ra.get_certificate()` - retrieve an existing certificate.
+ * `ra.request_certificate()` - request a new certificate.
+ * `ra.revoke_certificate()` - revoke a certificate.
+ * `ra.take_certificate_off_hold()` - take a certificate off hold.
+"""
+
+from ipalib import api
+from ipalib import Backend
+from ipalib import errors
+from ipaserver.install import certs
+import os
+
+class rabase(Backend):
+ """
+ Request Authority backend plugin.
+ """
+ def __init__(self):
+ if api.env.home:
+ self.sec_dir = api.env.dot_ipa + os.sep + 'alias'
+ self.pwd_file = self.sec_dir + os.sep + '.pwd'
+ self.serial_file = self.sec_dir + os.sep + 'ca_serialno'
+ else:
+ self.sec_dir = "/etc/httpd/alias"
+ self.pwd_file = "/etc/httpd/alias/pwdfile.txt"
+ self.serial_file = certs.CA_SERIALNO
+ super(rabase, self).__init__()
+
+
+ def check_request_status(self, request_id):
+ """
+ Check status of a certificate signing request.
+
+ :param request_id: request ID
+ """
+ raise errors.NotImplementedError(name='%s.check_request_status' % self.name)
+
+ def get_certificate(self, serial_number=None):
+ """
+ Retrieve an existing certificate.
+
+ :param serial_number: certificate serial number
+ """
+ raise errors.NotImplementedError(name='%s.check_request_status' % self.name)
+
+ def request_certificate(self, csr, request_type='pkcs10'):
+ """
+ Submit certificate signing request.
+
+ :param csr: The certificate signing request.
+ :param request_type: The request type (defaults to ``'pkcs10'``).
+ """
+ raise errors.NotImplementedError(name='%s.check_request_status' % self.name)
+
+ def revoke_certificate(self, serial_number, revocation_reason=0):
+ """
+ Revoke a certificate.
+
+ The integer ``revocation_reason`` code must have one of these values:
+
+ * ``0`` - unspecified
+ * ``1`` - keyCompromise
+ * ``2`` - cACompromise
+ * ``3`` - affiliationChanged
+ * ``4`` - superseded
+ * ``5`` - cessationOfOperation
+ * ``6`` - certificateHold
+ * ``8`` - removeFromCRL
+ * ``9`` - privilegeWithdrawn
+ * ``10`` - aACompromise
+
+ Note that reason code ``7`` is not used. See RFC 5280 for more details:
+
+ http://www.ietf.org/rfc/rfc5280.txt
+
+ :param serial_number: Certificate serial number.
+ :param revocation_reason: Integer code of revocation reason.
+ """
+ raise errors.NotImplementedError(name='%s.check_request_status' % self.name)
+
+ def take_certificate_off_hold(self, serial_number):
+ """
+ Take revoked certificate off hold.
+
+ :param serial_number: Certificate serial number.
+ """
+ raise errors.NotImplementedError('%s.check_request_status' % self.name)
+
diff --git a/ipaserver/plugins/selfsign.py b/ipaserver/plugins/selfsign.py
new file mode 100644
index 000000000..4bec0665a
--- /dev/null
+++ b/ipaserver/plugins/selfsign.py
@@ -0,0 +1,126 @@
+# Authors:
+# Rob Crittenden <rcritten@@redhat.com>
+#
+# Copyright (C) 2009 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 RA activities.
+
+The `ra` plugin provides access to the CA to issue, retrieve, and revoke
+certificates via the following methods:
+
+ * `ra.check_request_status()` - check certificate request status.
+ * `ra.get_certificate()` - retrieve an existing certificate.
+ * `ra.request_certificate()` - request a new certificate.
+ * `ra.revoke_certificate()` - revoke a certificate.
+ * `ra.take_certificate_off_hold()` - take a certificate off hold.
+"""
+
+from ipalib import api, SkipPluginModule
+if api.env.ra_plugin != 'selfsign':
+ # In this case, abort loading this plugin module...
+ raise SkipPluginModule(reason='selfsign is not selected as RA plugin, it is %s' % api.env.ra_plugin)
+from ipalib import Backend
+from ipalib import errors
+import subprocess
+import os
+from ipaserver.plugins import rabase
+from ipaserver.install import certs
+import tempfile
+from OpenSSL import crypto
+
+class ra(rabase.rabase):
+ """
+ Request Authority backend plugin.
+ """
+
+ def request_certificate(self, csr, request_type='pkcs10'):
+ """
+ Submit certificate signing request.
+
+ :param csr: The certificate signing request.
+ :param request_type: The request type (defaults to ``'pkcs10'``).
+ """
+ (csr_fd, csr_name) = tempfile.mkstemp()
+ os.write(csr_fd, csr)
+ os.close(csr_fd)
+ (cert_fd, cert_name) = tempfile.mkstemp()
+ os.close(cert_fd)
+
+ serialno = certs.next_serial(self.serial_file)
+
+ try:
+ args = [
+ "/usr/bin/certutil",
+ "-C",
+ "-d", self.sec_dir,
+ "-c", "CA certificate",
+ "-i", csr_name,
+ "-o", cert_name,
+ "-m", str(serialno),
+ "-v", "60",
+ "-1",
+ "-5",
+ "-6",
+ "-a",
+ "-f", self.pwd_file]
+ self.log.debug("issue cert: %s" % str(args))
+ p = subprocess.Popen(args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, close_fds=True)
+ p.stdin.write("0\n1\n2\n3\n9\ny\n")
+ p.stdin.write("0\n9\nn\n")
+ p.stdin.write("1\n9\nn\n")
+ (stdout, stderr) = p.communicate()
+ self.log.debug("stdout = %s" % stdout)
+ self.log.debug("stderr = %s" % stderr)
+ finally:
+ os.remove(csr_name)
+
+ try:
+ cert_fd = open(cert_name)
+ cert = cert_fd.read()
+ cert_fd.close()
+ finally:
+ os.remove(cert_name)
+
+ try:
+ # Grab the subject, reverse it, combine it and return it
+ x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
+ sub = x509.get_subject().get_components()
+ sub.reverse()
+ subject = ""
+ for s in sub:
+ subject = subject + "%s=%s," % (s[0], s[1])
+ subject = subject[:-1]
+
+ serial = x509.get_serial_number()
+ except crypto.Error, e:
+ raise errors.GenericError(format='Unable to decode certificate in entry: %s' % str(e))
+
+ # To make it look like dogtag return just the base64 data.
+ cert = cert.replace('\n','')
+ cert = cert.replace('\r','')
+ s = cert.find('-----BEGIN CERTIFICATE-----')
+ e = cert.find('-----END CERTIFICATE-----')
+ s = s + 27
+ cert = cert[s:e]
+
+ return {'status':0, 'subject': subject, 'certificate':cert, 'serial': "0x%x" % serial}
+
+api.register(ra)