diff options
Diffstat (limited to 'base/common/python/pki/nssdb.py')
-rw-r--r-- | base/common/python/pki/nssdb.py | 231 |
1 files changed, 180 insertions, 51 deletions
diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py index cad89081e..3c0ac0682 100644 --- a/base/common/python/pki/nssdb.py +++ b/base/common/python/pki/nssdb.py @@ -1,5 +1,6 @@ # Authors: # Endi S. Dewata <edewata@redhat.com> +# Dinesh Prasnath M K <dmoluguw@redhat.com> # # This program is free software; you can redistribute it and/or modify # it under the terms of the Lesser GNU General Public License as published by @@ -294,7 +295,6 @@ class NSSDatabase(object): exts = [] for generic_ext in generic_exts: - data_file = os.path.join(tmpdir, 'csr-ext-%d' % counter) with open(data_file, 'w') as f: f.write(generic_ext['data']) @@ -339,95 +339,224 @@ class NSSDatabase(object): finally: shutil.rmtree(tmpdir) - def create_self_signed_ca_cert(self, subject_dn, request_file, cert_file, - serial='1', validity=240): - + def create_cert(self, request_file, cert_file, serial, issuer=None, + key_usage_ext=None, basic_constraints_ext=None, + aki_ext=None, ski_ext=None, aia_ext=None, ext_key_usage_ext=None, + validity=None): cmd = [ 'certutil', '-C', - '-x', '-d', self.directory ] + # Check if it's self signed + if issuer: + cmd.extend(['-c', issuer]) + else: + cmd.extend('-x') + if self.token: cmd.extend(['-h', self.token]) cmd.extend([ '-f', self.password_file, - '-c', subject_dn, '-a', '-i', request_file, '-o', cert_file, - '-m', serial, - '-v', str(validity), - '--keyUsage', 'digitalSignature,nonRepudiation,certSigning,crlSigning,critical', - '-2', - '-3', - '--extSKID', - '--extAIA' + '-m', serial ]) - p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + if validity: + cmd.extend(['-v', str(validity)]) keystroke = '' - # Is this a CA certificate [y/N]? - keystroke += 'y\n' + if aki_ext: + cmd.extend(['-3']) + + # Enter value for the authKeyID extension [y/N] + if 'auth_key_id' in aki_ext: + keystroke += 'y\n' + + # Enter value for the key identifier fields,enter to omit: + keystroke += aki_ext['auth_key_id'] + + keystroke += '\n' + + # Select one of the following general name type: + # TODO: General Name type isn't used as of now for AKI + keystroke += '0\n' + + if 'auth_cert_serial' in aki_ext: + keystroke += aki_ext['auth_cert_serial'] + + keystroke += '\n' + + # Is this a critical extension [y/N]? + if 'critical' in aki_ext and aki_ext['critical']: + keystroke += 'y' + + keystroke += '\n' + + # Key Usage Constraints + if key_usage_ext: + + cmd.extend(['--keyUsage']) + + usages = [] + for usage in key_usage_ext: + if key_usage_ext[usage]: + usages.append(usage) + + cmd.extend([','.join(usages)]) - # Enter the path length constraint, enter to skip [<0 for unlimited path]: - keystroke += '\n' + # Extended key usage + if ext_key_usage_ext: + cmd.extend(['--extKeyUsage']) + usages = [] + for usage in ext_key_usage_ext: + if ext_key_usage_ext[usage]: + usages.append(usage) - # Is this a critical extension [y/N]? - keystroke += 'y\n' + cmd.extend([','.join(usages)]) - # Enter value for the authKeyID extension [y/N]? - keystroke += 'y\n' + # Basic constraints + if basic_constraints_ext: - # TODO: generate SHA1 ID (see APolicyRule.formSHA1KeyId()) - # Enter value for the key identifier fields,enter to omit: - keystroke += '2d:7e:83:37:75:5a:fd:0e:8d:52:a3:70:16:93:36:b8:4a:d6:84:9f\n' + cmd.extend(['-2']) - # Select one of the following general name type: - keystroke += '0\n' + # Is this a CA certificate [y/N]? + if basic_constraints_ext['ca']: + keystroke += 'y' - # Enter value for the authCertSerial field, enter to omit: - keystroke += '\n' + keystroke += '\n' - # Is this a critical extension [y/N]? - keystroke += '\n' + # Enter the path length constraint, enter to skip [<0 for unlimited path]: + if basic_constraints_ext['path_length']: + keystroke += basic_constraints_ext['path_length'] - # TODO: generate SHA1 ID (see APolicyRule.formSHA1KeyId()) - # Adding Subject Key ID extension. - # Enter value for the key identifier fields,enter to omit: - keystroke += '2d:7e:83:37:75:5a:fd:0e:8d:52:a3:70:16:93:36:b8:4a:d6:84:9f\n' + keystroke += '\n' - # Is this a critical extension [y/N]? - keystroke += '\n' + # Is this a critical extension [y/N]? + if basic_constraints_ext['critical']: + keystroke += 'y' - # Enter access method type for Authority Information Access extension: - keystroke += '2\n' + keystroke += '\n' - # Select one of the following general name type: - keystroke += '7\n' + if ski_ext: + cmd.extend(['--extSKID']) - # TODO: replace with actual hostname name and port number - # Enter data: - keystroke += 'http://server.example.com:8080/ca/ocsp\n' + # Adding Subject Key ID extension. + # Enter value for the key identifier fields,enter to omit: + if 'sk_id' in ski_ext: + keystroke += ski_ext['sk_id'] - # Select one of the following general name type: - keystroke += '0\n' + keystroke += '\n' - # Add another location to the Authority Information Access extension [y/N] - keystroke += '\n' + # Is this a critical extension [y/N]? + if 'critical' in ski_ext and ski_ext['critical']: + keystroke += 'y' - # Is this a critical extension [y/N]? - keystroke += '\n' + keystroke += '\n' + + if aia_ext: + cmd.extend(['--extAIA']) + + # To ensure whether this is the first AIA being added + firstentry = True + + # Enter access method type for Authority Information Access extension: + for s in aia_ext: + if not firstentry: + keystroke += 'y\n' + + # 1. CA Issuers + if s == 'ca_issuers': + keystroke += '1' + + # 2. OCSP + if s == 'ocsp': + keystroke += '2' + keystroke += '\n' + for gn in aia_ext[s]['uri']: + # 7. URI + keystroke += '7\n' + # Enter data + keystroke += gn + '\n' + + # Any other number to finish + keystroke += '0\n' + + # One entry is done. + firstentry = False + + # Add another location to the Authority Information Access extension [y/N] + keystroke += '\n' + + # Is this a critical extension [y/N]? + if 'critical' in aia_ext and aia_ext['critical']: + keystroke += 'y' + + keystroke += '\n' + + p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) p.communicate(keystroke) rc = p.wait() + return rc + + def create_self_signed_ca_cert(self, request_file, cert_file, + serial='1', validity=240): + + # --keyUsage + key_usage_ext = { + 'digitalSignature': True, + 'nonRepudiation': True, + 'certSigning': True, + 'crlSigning': True, + 'critical': True + } + + # -2 + basic_constraints_ext = { + 'path_length': None + } + + # FIXME: do not hard-code AKI extension + # -3 + aki_ext = { + 'auth_key_id': '0x2d7e8337755afd0e8d52a370169336b84ad6849f' + } + + # FIXME: do not hard-code SKI extension + # --extSKID + ski_ext = { + 'sk_id': '0x2d7e8337755afd0e8d52a370169336b84ad6849f' + } + + # FIXME: do not hard-code AIA extension + # --extAIA + aia_ext = { + 'ocsp': { + 'uri': ['http://server.example.com:8080/ca/ocsp'] + } + + } + + rc = self.create_cert( + request_file=request_file, + cert_file=cert_file, + serial=serial, + validity=validity, + key_usage_ext=key_usage_ext, + basic_constraints_ext=basic_constraints_ext, + aki_ext=aki_ext, + ski_ext=ski_ext, + aia_ext=aia_ext) + if rc: raise Exception('Failed to generate self-signed CA certificate. RC: %d' % rc) |