summaryrefslogtreecommitdiffstats
path: root/func
diff options
context:
space:
mode:
authorSeth Vidal <skvidal@fedoraproject.org>2007-09-24 15:44:26 -0400
committerSeth Vidal <skvidal@fedoraproject.org>2007-09-24 15:44:26 -0400
commit122714e5589843c5f283ad935b20345576d24ca6 (patch)
treef3b809bde47d268e3b771d5aa4aed84064ba300f /func
parent8454fe3216f935746fad17a8c48f4df0e40a0d0d (diff)
downloadthird_party-func-122714e5589843c5f283ad935b20345576d24ca6.tar.gz
third_party-func-122714e5589843c5f283ad935b20345576d24ca6.tar.xz
third_party-func-122714e5589843c5f283ad935b20345576d24ca6.zip
add certmaster startup and execute script
move certmaster config file into etc path move certmaster.py into func path
Diffstat (limited to 'func')
-rwxr-xr-xfunc/certmaster.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/func/certmaster.py b/func/certmaster.py
new file mode 100755
index 0000000..02c8013
--- /dev/null
+++ b/func/certmaster.py
@@ -0,0 +1,171 @@
+#!/usr/bin/python
+
+"""
+cert master listener
+
+Copyright 2007, Red Hat, Inc
+see AUTHORS
+
+This software may be freely redistributed under the terms of the GNU
+general public license.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
+"""
+
+# standard modules
+import SimpleXMLRPCServer
+import string
+import socket
+import sys
+import os
+import os.path
+import traceback
+from OpenSSL import crypto
+import sha
+
+#from func.server import codes
+import func
+import func.certs
+
+
+class SimpleConfigFile(object):
+ """simple config file object:
+ reads in key=value pairs from a file and stores each as an attribute"""
+
+ def __init__(self, filename):
+ self.fn = filename
+ fo = open(filename, 'r')
+ for line in fo.readlines():
+ if line.startswith('#'): continue
+ if line.strip() == '': continue
+ (key, val) = line.split('=')
+ key = key.strip().lower()
+ val = val.strip()
+ setattr(self, key, val)
+ fo.close()
+
+
+class CertMaster(object):
+ def __init__(self, conf_file):
+ self.cfg = SimpleConfigFile(conf_file)
+ self.listen_addr = 'localhost'
+ self.listen_port = '51235'
+ self.cadir = '/etc/pki/func/ca'
+ self.certroot = '/etc/pki/func/ca/certs'
+ self.csrroot = '/etc/pki/func/ca/csrs'
+ self.autosign = True
+ for attr in ['listen_addr', 'listen_port', 'cadir', 'certroot',
+ 'csrroot']:
+ if hasattr(self.cfg, attr):
+ setattr(self, attr, getattr(self.cfg, attr))
+ if hasattr(self.cfg, 'autosign'):
+ if getattr(self.cfg, 'autosign').lower() in ['yes', 'true', 1, 'on']:
+ self.autosign = True
+ elif getattr(self.cfg, 'autosign').lower() in ['no', 'false', 0, 'off']:
+ self.autosign = False
+ # open up the cakey and cacert so we have them available
+ ca_key_file = '%s/funcmaster.key' % self.cadir
+ ca_cert_file = '%s/funcmaster.crt' % self.cadir
+ self.cakey = func.certs.retrieve_key_from_file(ca_key_file)
+ self.cacert = func.certs.retrieve_cert_from_file(ca_cert_file)
+
+ for dirpath in [self.cadir, self.certroot, self.csrroot]:
+ if not os.path.exists(dirpath):
+ os.makedirs(dirpath)
+
+ # setup handlers
+ self.handlers = {
+ 'wait_for_cert': self.wait_for_cert,
+ }
+
+ def _dispatch(self, method, params):
+ if method == 'trait_names' or method == '_getAttributeNames':
+ return self.handlers.keys()
+
+ if method in self.handlers.keys():
+ return self.handlers[method](*params)
+ else:
+ pass
+ #raise codes.InvalidMethodException
+
+
+ def wait_for_cert(self, csrbuf):
+ """
+ takes csr as a string
+ returns True, caller_cert, ca_cert
+ returns False, '', ''
+ """
+
+ try:
+ csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csrbuf)
+ except crypto.Error, e:
+ #XXX need to raise a fault here and document it - but false is just as good
+ return False, '', ''
+
+ requesting_host = csrreq.get_subject().CN
+ certfile = '%s/%s.pem' % (self.certroot, requesting_host)
+ csrfile = '%s/%s.csr' % (self.csrroot, requesting_host)
+
+ # check for old csr on disk
+ # if we have it - compare the two - if they are not the same - raise a fault
+ if os.path.exists(csrfile):
+ oldfo = open(csrfile)
+ oldcsrbuf = oldfo.read()
+ oldsha = sha.new()
+ oldsha.update(oldcsrbuf)
+ olddig = oldsha.hexdigest()
+ newsha = sha.new()
+ newsha.update(csrbuf)
+ newdig = newsha.hexdigest()
+ if not newdig == olddig:
+ # XXX raise a proper fault
+ return False, '', ''
+
+ # look for a cert:
+ # if we have it, then return True, etc, etc
+ if os.path.exists(certfile):
+ slavecert = crypto.load_certificate(crypto.FILETYPE_PEM, certfile)
+
+ cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert)
+ cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert)
+ return True, cert_buf, cacert_buf
+
+ # if we don't have a cert then:
+ # if we're autosign then sign it, write out the cert and return True, etc, etc
+ # else write out the csr
+
+ if self.autosign:
+ slavecert = func.certs.create_slave_certificate(csrreq,
+ self.cakey, self.cacert, self.cadir)
+
+ destfo = open(certfile, 'w')
+ destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert))
+ destfo.close()
+ del destfo
+ cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert)
+ cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert)
+ return True, cert_buf, cacert_buf
+
+ else:
+ # write the csr out to a file to be dealt with by the admin
+ destfo = open(csrfile, 'w')
+ destfo.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, csrreq))
+ destfo.close()
+ del destfo
+ return False, '', ''
+
+ return False, '', ''
+
+
+def serve(xmlrpcinstance):
+
+ """
+ Code for starting the XMLRPC service.
+ """
+
+ server =FuncXMLRPCServer((xmlrpcinstance.listen_addr, xmlrpcinstance.list_port))
+ server.logRequests = 0 # don't print stuff to console
+ server.register_instance(xmlrpcinstance)
+ server.serve_forever()