summaryrefslogtreecommitdiffstats
path: root/ipaserver/plugins/selfsign.py
blob: 0ba7a7c44a588d18527b86d617cf6f226c3106c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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_number': "0x%x" % serial}

api.register(ra)