summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/cert.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib/plugins/cert.py')
-rw-r--r--ipalib/plugins/cert.py53
1 files changed, 49 insertions, 4 deletions
diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py
index e38ec181..1681a22f 100644
--- a/ipalib/plugins/cert.py
+++ b/ipalib/plugins/cert.py
@@ -30,6 +30,24 @@ from ipalib import Command, Str, Int, Bytes, Flag
from ipalib import errors
from ipalib.plugins.virtual import *
import base64
+from OpenSSL import crypto
+
+def get_serial(certificate):
+ """
+ Given a certificate, return the serial number in that cert
+
+ In theory there should be only one cert per object so even if we get
+ passed in a list/tuple only return the first one.
+ """
+ if type(certificate) in (list, tuple):
+ certificate = certificate[0]
+ try:
+ x509 = crypto.load_certificate(crypto.FILETYPE_ASN1, certificate)
+ serial = str(x509.get_serial_number())
+ except crypto.Error:
+ raise errors.GenericError(format='Unable to decode certificate in entry')
+
+ return serial
def validate_csr(ugettext, csr):
"""
@@ -76,14 +94,14 @@ class cert_request(VirtualCommand):
# See if the service exists and punt if it doesn't and we aren't
# going to add it
try:
- service = api.Command['service_show'](principal, **skw)
- if service.get('usercertificate'):
+ (dn, service) = api.Command['service_show'](principal, **skw)
+ if 'usercertificate' in service:
# FIXME, what to do here? Do we revoke the old cert?
- raise errors.GenericError(format='entry already has a certificate')
+ raise errors.GenericError(format='entry already has a certificate, serial number %s' % get_serial(service['usercertificate']))
except errors.NotFound, e:
if not add:
- raise e
+ raise errors.NotFound(reason="The service principal for this request doesn't exist.")
# Request the certificate
result = self.Backend.ra.request_certificate(csr, **kw)
@@ -104,6 +122,33 @@ class cert_request(VirtualCommand):
else:
textui.print_plain('Failed to submit a certificate request.')
+ def run(self, *args, **options):
+ """
+ Dispatch to forward() and execute() to do work locally and on the
+ server.
+ """
+ if self.env.in_server:
+ return self.execute(*args, **options)
+
+ # Client-side code
+ csr = args[0]
+ if csr[:7] == "file://":
+ file = csr[7:]
+ try:
+ f = open(file, "r")
+ csr = f.readlines()
+ f.close()
+ except IOError, err:
+ raise errors.ValidationError(name='csr', error=err[1])
+ csr = "".join(csr)
+ # We just want the CSR bits, make sure there is nothing else
+ s = csr.find("-----BEGIN NEW CERTIFICATE REQUEST-----")
+ e = csr.find("-----END NEW CERTIFICATE REQUEST-----")
+ if s >= 0:
+ csr = csr[s+40:e]
+ csr = csr.decode('UTF-8')
+ return self.forward(csr, **options)
+
api.register(cert_request)