sha1 supprt checkpoint
authorJude Nagurney <jude@pwan.org>
Sun, 11 Oct 2015 20:28:06 +0000 (16:28 -0400)
committerJude Nagurney <jude@pwan.org>
Sun, 11 Oct 2015 20:28:06 +0000 (16:28 -0400)
MANIFEST.in
certmaster.spec
certmaster/certmaster.py
certmaster/certs.py
certmaster/commonconfig.py
certmaster/config.py
scripts/certmaster-sync
tests/certmaster.conf.tst
tests/minion.conf.tst
tests/test-certmaster.sh

index 9633326..928aa6c 100644 (file)
@@ -7,5 +7,5 @@ recursive-include po *.pot
 recursive-include triggers *
 include AUTHORS
 include LICENSE
-include README
+include README.md
 
index 1b51c5b..0e68308 100644 (file)
@@ -111,7 +111,7 @@ rm -fr $RPM_BUILD_ROOT
 %dir /var/lib/certmaster/triggers/remove/post
 /var/lib/certmaster/triggers/sign/post/certmaster-sync
 /var/lib/certmaster/triggers/remove/post/certmaster-sync
-%doc AUTHORS README LICENSE
+%doc AUTHORS README.md LICENSE
 %{_mandir}/man1/*.1.gz
 
 
index 36f2bc4..5947362 100644 (file)
@@ -21,6 +21,7 @@ import sys
 import traceback
 import os
 import os.path
+import warnings
 from OpenSSL import crypto
 
 try:
@@ -32,6 +33,8 @@ except ImportError:
         @staticmethod
         def new(algo):
             if algo == 'sha1':
+                # TODO: jude: was warnings even available in 2.4 ?
+                warnings.warn("sha1 is deprecated", DeprecationWarning)
                 return sha.new()
             raise ValueError, "Bad checksum type"
 
@@ -82,7 +85,7 @@ class CertMaster(object):
                 if not os.path.exists(s_cadir):
                     os.makedirs(s_cadir)
                 if not os.path.exists(s_ca_key_file) and not os.path.exists(s_ca_cert_file):
-                    certs.create_ca(CN=mycn, ca_key_file=s_ca_key_file, ca_cert_file=s_ca_cert_file)
+                    certs.create_ca(CN=mycn, ca_key_file=s_ca_key_file, ca_cert_file=s_ca_cert_file, hash_function=a_ca.hash_function)
             except (IOError, OSError), e:
                 print 'Cannot make certmaster certificate authority keys/certs for CA %s, aborting: %s' % (s_caname, e)
                 sys.exit(1)
@@ -153,10 +156,10 @@ class CertMaster(object):
         if os.path.exists(csrfile):
             oldfo = open(csrfile)
             oldcsrbuf = oldfo.read()
-            oldsha = hashlib.new('sha1')
+            oldsha = hashlib.new(certauth.hash_function)
             oldsha.update(oldcsrbuf)
             olddig = oldsha.hexdigest()
-            newsha = hashlib.new('sha1')
+            newsha = hashlib.new(certauth.hash_function)
             newsha.update(csrbuf)
             newdig = newsha.hexdigest()
             if not newdig == olddig:
@@ -268,7 +271,7 @@ class CertMaster(object):
 
         certfile = '%s/%s.cert' % (certauth.certroot, requesting_host)
         self.logger.info("Signing for csr %s requested" % certfile)
-        thiscert = certs.create_slave_certificate(csrreq, certauth.cakey, certauth.cacert, certauth.cadir)
+        thiscert = certs.create_slave_certificate(csrreq, certauth.cakey, certauth.cacert, certauth.cadir, certauth.hash_function)
 
         destfo = open(certfile, 'w')
         destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, thiscert))
index d6f8b14..5771691 100644 (file)
@@ -89,7 +89,7 @@ def retrieve_cert_from_file(certfile):
     return cert
 
 
-def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None):
+def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None, hash_function='sha256'):
     cakey = make_keypair(dest=ca_key_file)
     careq = make_csr(cakey, cn=CN)
     cacert = crypto.X509()
@@ -103,7 +103,7 @@ def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_f
     xt = crypto.X509Extension('basicConstraints',1,'CA:TRUE')
     # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
     cacert.add_extensions((xt,))
-    cacert.sign(cakey, 'sha1')
+    cacert.sign(cakey, hash_function)
     if ca_cert_file:
         destfo = open(ca_cert_file, 'w')
         destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
@@ -133,7 +133,7 @@ def _set_serial_number(cadir, last):
     f.close()
 
 
-def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
+def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None, hash_function='sha256'):
     cert = crypto.X509()
     cert.set_serial_number(_get_serial_number(cadir))
     cert.gmtime_adj_notBefore(0)
@@ -145,7 +145,7 @@ def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
     xt = crypto.X509Extension('basicConstraints', False ,'CA:FALSE')
     # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
     cert.add_extensions((xt,))
-    cert.sign(cakey, 'sha1')
+    cert.sign(cakey, hash_function)
     if slave_cert_file:
         destfo = open(slave_cert_file, 'w')
         destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
index 5d0361e..c062d28 100644 (file)
@@ -29,6 +29,7 @@ class CMConfig(BaseConfig):
     sync_certs = BoolOption(False)
     peering = BoolOption(True)
     peerroot =  Option('/var/lib/certmaster/peers')
+    hash_function = Option('sha256')
 
 class MinionConfig(BaseConfig):
     log_level = Option('INFO')
index 2cec66f..c6e9174 100644 (file)
@@ -17,7 +17,6 @@
 
 import os
 import sys
-import warnings
 import copy
 import urlparse
 from ConfigParser import NoSectionError, NoOptionError, ConfigParser
@@ -448,7 +447,7 @@ class BaseConfig(object):
         self.cfg.write(fileobj)
 
     def getConfigOption(self, option, default=None):
-        warnings.warn('getConfigOption() will go away in a future version of Yum.\n'
+        warnings.warn('getConfigOption() will go away in a future version of certmaster.\n'
                 'Please access option values as attributes or using getattr().',
                 DeprecationWarning)
         if hasattr(self, option):
@@ -456,7 +455,7 @@ class BaseConfig(object):
         return default
 
     def setConfigOption(self, option, value):
-        warnings.warn('setConfigOption() will go away in a future version of Yum.\n'
+        warnings.warn('setConfigOption() will go away in a future version of certmaster.\n'
                 'Please set option values as attributes or using setattr().',
                 DeprecationWarning)
         if hasattr(self, option):
@@ -481,16 +480,28 @@ def read_config(config_file, BaseConfigDerived):
 
     ## Add the default items when just using a single ca
     opts.ca[''] = BaseConfigDerived()
+    opts.ca[''].hash_function = None
     opts.ca[''].populate(confparser,'main')
 
+    if opts.ca[''].hash_function == 'sha1':
+        log.warning('hash_function value of sha1 is deprecated', DeprecationWarning)
+    elif opts.ca[''].hash_function == 'md5':
+        print >> sys.stderr, "Error:  hash_function of md5 is not supported" 
+
     ## Add additonal ca sections
     sections = confparser.sections()
     for a_section in sections:
         if a_section.startswith('ca:'):
             ca_name = a_section[3:]
             opts.ca[ca_name] = BaseConfigDerived()
+            opts.ca[ca_name].hash_function = None
             opts.ca[ca_name].populate(confparser,a_section)
             opts.ca[ca_name].cakey = None
             opts.ca[ca_name].cacert = None
+
+            if opts.ca[ca_name].hash_function == 'sha1':
+                warnings.warn('hash_function value of sha1 is deprecated in ca:%s section' % ca_name, DeprecationWarning)
+            elif opts.ca[ca_name].hash_function == 'md5':
+                print >> sys.stderr, "Error:  hash_function of md5 is not supported in ca:% section" % ca_name 
     
     return opts
index ca7710e..8e6db44 100644 (file)
@@ -7,6 +7,7 @@
 
 import os
 import sys
+import warning
 try:
     import hashlib
 except ImportError:
@@ -16,6 +17,7 @@ except ImportError:
         @staticmethod
         def new(algo):
             if algo == 'sha1':
+                warnings.warn('sha1 is deprecated',DeprecationWarning)
                 return sha.new()
             raise ValueError, "Bad checksum type"
 
@@ -76,7 +78,7 @@ def remote_peers(hosts):
 
 def local_certs():
     """
-    Returns (hostname, sha1) hash of local certs
+    Returns (hostname, hashval) hash of local certs
     """
     globby = '*.%s' % cm.cfg.cert_extension
     globby = os.path.join(cm.cfg.certroot, globby)
@@ -85,12 +87,12 @@ def local_certs():
     for f in files:
         hostname = os.path.basename(f).replace('.' + cm.cfg.cert_extension, '')
         dirname = os.path.dirname(f)
-        digest = checksum(f)
+        digest = checksum(f,cm.cfg.hashfunc)
         results.append([hostname, digest, dirname])
     return results
 
-def checksum(f):
-    thissum = hashlib.new('sha1')
+def checksum(f,hashfunc):
+    thissum = hashlib.new(hashfunc)
     if os.path.exists(f):
         fo = open(f, 'r')
         data = fo.read()
index e0188b5..e4c294b 100644 (file)
@@ -21,3 +21,19 @@ cert_dir = /etc/pki/certmaster/test
 certroot = /var/lib/certmaster/test/certs
 csrroot = /var/lib/certmaster/test/csrs
 
+[ca:sha1]
+autosign = yes
+cadir = /etc/pki/certmaster/sha1-ca
+cert_dir = /etc/pki/certmaster/sha1
+certroot = /var/lib/certmaster/sha1/certs
+csrroot = /var/lib/certmaster/sha1/csrs
+hash_function = sha224
+
+[ca:sha224]
+autosign = yes
+cadir = /etc/pki/certmaster/sha224-ca
+cert_dir = /etc/pki/certmaster/sha224
+certroot = /var/lib/certmaster/sha224/certs
+csrroot = /var/lib/certmaster/sha224/csrs
+hash_function = sha224
+
index 9e44013..f8fd330 100644 (file)
@@ -9,4 +9,13 @@ cert_dir = /etc/pki/certmaster
 
 [ca:test]
 cert_dir = /etc/pki/certmaster-test
+hash_function = sha256
+
+[ca:sha1]
+cert_dir = /etc/pki/certmaster-sha1
+hash_function = sha1
+
+[ca:sha224]
+cert_dir = /etc/pki/certmaster-sha224
+hash_function = sha224
 
index b9c6be1..11e7565 100755 (executable)
@@ -178,6 +178,9 @@ test_TestCA_Autosigning()
     subject=`openssl x509 -in /etc/pki/certmaster-test/testcert.pwan.co.cert -subject -noout`
     [[ $subject == *"CN=testcert.pwan.co"* ]]
 
+    openssl x509 -in /etc/pki/certmaster-test/testcert.pwan.co.cert  -text | grep Signature | grep sha256
+    assertTrue "testcert.pwan.co.cert has a sha256 hash" $?
+
     openssl rsa -in /etc/pki/certmaster-test/testcert.pwan.co.pem -check > /dev/null 2>&1
     assertTrue "test.pwan.co.pem OK" $?
     openssl req -text -noout -verify -in /etc/pki/certmaster-test/testcert.pwan.co.csr > /dev/null 2>&1
@@ -199,6 +202,31 @@ test_TestCA_Autosigning()
 
 }
 
+test_MD5CA_Attempy() {
+
+    # TODO:  Verify attempts to create MD5 certs fail
+    assertTrue "TODO" false
+}
+
+test_Sha1CA_Autosigning() {
+
+    # TODO:  Verify a deprecation warning was issued ?
+
+    certmaster-request --hostname testcert.pwan.co --ca sha1
+    openssl x509 -in /etc/pki/certmaster-sha1/testcert.pwan.co.cert  -text | grep Signature | grep sha1
+    assertTrue "testcert.pwan.co.cert has a sha1 hash" $?
+
+}
+
+test_Sha224CA_Autosigning() {
+
+    # TODO:  Verify /etc/pki/certmaster-test/testcert.pwan.co.cert is using sha224
+    certmaster-request --hostname testcert.pwan.co --ca sha224
+    openssl x509 -in /etc/pki/certmaster-sha224/testcert.pwan.co.cert  -text | grep Signature | grep sha224
+    assertTrue "testcert.pwan.co.cert has a sha224 hash" $?
+
+}
+
 test_DefaultCA_NonAutosigning() {
 
     # Turn on job control, so 'fg' is available