def test_x509_name(self): n = X509.X509_Name() n.C = 'US' # It seems this actually needs to be a real 2 letter country code n.SP = 'State or Province' n.L = 'locality name' n.O = 'orhanization name' n.OU = 'org unit' n.CN = 'common name' n.Email = '*****@*****.**' n.serialNumber = '1234' n.SN = 'surname' n.GN = 'given name' n.givenName = 'name given' assert len(n) == 11, len(n) tl = map(x509_name_entry2tuple, x509_name2list(n)) assert len(tl) == len(n), len(tl) x509_n = m2.x509_name_new() for o in map(tuple2x509_name_entry, tl): m2.x509_name_add_entry(x509_n, o._ptr(), -1, 0) o._pyfree = 0 # Take care of underlying object n1 = X509.X509_Name(x509_n) assert n.as_text() == n1.as_text(), n1.as_text()
def test_x509_name(self): n = X509.X509_Name() # It seems this actually needs to be a real 2 letter country code n.C = b'US' n.SP = b'State or Province' n.L = b'locality name' n.O = b'orhanization name' n.OU = b'org unit' n.CN = b'common name' n.Email = b'*****@*****.**' n.serialNumber = b'1234' n.SN = b'surname' n.GN = b'given name' n.givenName = b'name given' self.assertEqual(len(n), 11, len(n)) # Thierry: this call to list seems extraneous... tl = [x509_name_entry2tuple(x) for x in x509_name2list(n)] self.assertEqual(len(tl), len(n), len(tl)) x509_n = m2.x509_name_new() for o in [tuple2x509_name_entry(x) for x in tl]: m2.x509_name_add_entry(x509_n, o._ptr(), -1, 0) o._pyfree = 0 # Take care of underlying object n1 = X509.X509_Name(x509_n) self.assertEqual(n.as_text(), n1.as_text(), n1.as_text())
def __init__(self, certificate, proxykey=None, full=True): if isinstance(certificate, Certificate): self._certificate = certificate elif isinstance(certificate, ProxyCertificate): self._certificate = certificate._proxy else: self._certificate = Certificate(certificate) self._full = full self._proxy = Certificate(key=proxykey) self._proxy.set_version(2) self.set_serial_number() issuer = self._certificate.get_subject() subject = X509.X509_Name() for n in issuer: m2.x509_name_add_entry(subject.x509_name, n.x509_name_entry, -1, 0) subject.add_entry_by_txt(field='CN', type=MBSTRING_ASC, entry=str(self._proxy.get_serial_number()),len=-1, loc=-1, set=0) # CURRENT - this partly fools the system that it has a globus legacy proxy (needed by grisu/grid) # can look up VOs, but can't access filesystems for running jobs with this on # subject.add_entry_by_txt(field='CN', type=MBSTRING_ASC, entry='proxy',len=-1, loc=-1, set=0) self._proxy.set_dn(subject) self._proxy.set_times(lifetime=43200) self._proxy.set_issuer_name(self._certificate.get_subject()) try: key_usage = self._certificate._certificate.get_ext('keyUsage') except LookupError: pass else: self._proxy.add_extension({'name':key_usage.get_name(), 'critical': key_usage.get_critical(), 'value': self._fix_key_usage(key_usage.get_value())}) if self._full: self._proxy.add_extension({'name':"proxyCertInfo", 'value': PCI_VALUE_FULL, 'critical': 1}) else: self._proxy.add_extension({'name': "proxyCertInfo", 'value': PCI_VALUE_LIMITED, 'critical': 1})
def _signRequest(self, x509Request, lifetime): notBefore = ASN1.ASN1_UTCTIME() notBefore.set_datetime(datetime.now(pytz.UTC)) notAfter = ASN1.ASN1_UTCTIME() notAfter.set_datetime(datetime.now(pytz.UTC) + lifetime) proxySubject = X509.X509_Name() for c in self.context.x509.get_subject(): m2.x509_name_add_entry(proxySubject._ptr(), c._ptr(), -1, 0) proxySubject.add_entry_by_txt('commonName', 0x1000, 'proxy', -1, -1, 0) proxy = X509.X509() proxy.set_version(2) proxy.set_subject(proxySubject) proxy.set_serial_number(long(time.time())) proxy.set_version(x509Request.get_version()) proxy.set_issuer(self.context.x509.get_subject()) proxy.set_pubkey(x509Request.get_pubkey()) # Make sure the proxy is not longer than any other inside the chain any_rfc_proxies = False for cert in self.context.x509List: if cert.get_not_after() < notAfter: notAfter = cert.get_not_after() try: cert.get_ext('1.3.6.1.5.5.7.1.14') any_rfc_proxies = True except: pass proxy.set_not_after(notAfter) proxy.set_not_before(notBefore) if any_rfc_proxies: raise NotImplementedError('RFC proxies not supported yet') proxy.sign(self.context.evpKey, 'sha1') return proxy
def generate_proxycert(new_pkey, cert, key, **kwargs): """Generate a proxy certificate. * new_pkey: EVP.PKey for the proxy certificate * cert: Issuer certificate * key: Issuer private key Optional arguments: * lifetime: proxy certificate lifetime, in seconds. Default: is 12 hours. * full: proxy type, full or limited. Default is False (limited proxy). * hash_algorithm: hash algorithm to use for certificate signing. Default: sha1. * globus_bug: do not use basicConstraints extension and do not allow Key Agreement. Default: true """ args = kwargs.copy() if 'args' in args: args.update(args.pop('args')) legacy = args.get('legacy', is_legacy_proxy(cert)) full = args.get('full', False) globus_bug = args.get('globus_bug', True) proxy = X509.X509() proxy.set_pubkey(new_pkey) proxy.set_version(2) now = int(time.time()) not_before = ASN1.ASN1_UTCTIME() not_before.set_time(now - CLOCK_SKEW) proxy.set_not_before(not_before) not_after = ASN1.ASN1_UTCTIME() not_after.set_time(now + args.get('lifetime', 12*60*60) + CLOCK_SKEW) proxy.set_not_after(not_after) proxy.set_issuer_name(cert.get_subject()) digest = EVP.MessageDigest('sha1') digest.update(new_pkey.as_der()) serial = struct.unpack("<L", digest.final()[:4])[0] proxy.set_serial_number(int(serial & 0x7fffffff)) # It is not completely clear what happens with memory allocation # within the next calls, so after building the whole thing we are # going to reload it through der encoding/decoding. proxy_subject = X509.X509_Name() subject = cert.get_subject() for idx in xrange(subject.entry_count()): entry = subject[idx].x509_name_entry m2.x509_name_add_entry(proxy_subject._ptr(), entry, -1, 0) if legacy: if full: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, "proxy", -1, -1, 0) else: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, "limited proxy", -1, -1, 0) else: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, str(serial), -1, -1, 0) proxy.set_subject(proxy_subject) if legacy: if globus_bug: proxy.add_ext(X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment", 1)) else: proxy.add_ext(X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement", 1)) proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE", 1)) # does not work (?) seems like need to add authorityCertIssuer # and authorityCertSerialNumber somehow, see rfc 3280 for more # details # try: # subjkey = cert.get_ext('subjectKeyIdentifier') # keyid = "keyid:%s" % subjkey.get_value() # ext = X509.new_extension("authorityKeyIdentifier", keyid, 0) # proxy.add_ext(ext) # except LookupError: # pass else: if globus_bug: proxy.add_ext(X509.new_extension("keyUsage", "Digital Signature, Key Encipherment, Data Encipherment", 1)) else: proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE", 1)) proxy.add_ext(X509.new_extension("keyUsage", "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement", 1)) if not legacy: if full: proxy.add_ext(X509.new_extension("proxyCertInfo", "critical, language:Inherit all", 1)) else: proxy.add_ext(X509.new_extension("proxyCertInfo", "critical, language:1.3.6.1.4.1.3536.1.1.1.9", 1)) sign_pkey = EVP.PKey() sign_pkey.assign_rsa(key, 0) proxy.sign(sign_pkey, args.get('hash_algorithm', 'sha1')) return X509.load_cert_string(proxy.as_pem())
def generate_proxycert(new_pkey, cert, key, **kwargs): """Generate a proxy certificate. * new_pkey: EVP.PKey for the proxy certificate * cert: Issuer certificate * key: Issuer private key Optional arguments: * lifetime: proxy certificate lifetime, in seconds. Default: is 12 hours. * full: proxy type, full or limited. Default is False (limited proxy). * hash_algorithm: hash algorithm to use for certificate signing. Default: sha1. * globus_bug: do not use basicConstraints extension and do not allow Key Agreement. Default: true """ args = kwargs.copy() if 'args' in args: args.update(args.pop('args')) legacy = args.get('legacy', is_legacy_proxy(cert)) full = args.get('full', False) globus_bug = args.get('globus_bug', True) proxy = X509.X509() proxy.set_pubkey(new_pkey) proxy.set_version(2) now = int(time.time()) not_before = ASN1.ASN1_UTCTIME() not_before.set_time(now - CLOCK_SKEW) proxy.set_not_before(not_before) not_after = ASN1.ASN1_UTCTIME() not_after.set_time(now + args.get('lifetime', 12 * 60 * 60) + CLOCK_SKEW) proxy.set_not_after(not_after) proxy.set_issuer_name(cert.get_subject()) digest = EVP.MessageDigest('sha1') digest.update(new_pkey.as_der()) serial = struct.unpack("<L", digest.final()[:4])[0] proxy.set_serial_number(int(serial & 0x7fffffff)) # Не совсем понятно, что и как с памятью в следующих операциях, # поэтому по завершению всего действа будет перезагрузка # сертификата через der proxy_subject = X509.X509_Name() subject = cert.get_subject() for idx in xrange(subject.entry_count()): entry = subject[idx].x509_name_entry m2.x509_name_add_entry(proxy_subject._ptr(), entry, -1, 0) if legacy: if full: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, "proxy", -1, -1, 0) else: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, "limited proxy", -1, -1, 0) else: proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, str(serial), -1, -1, 0) proxy.set_subject(proxy_subject) if legacy: if globus_bug: proxy.add_ext( X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment", 1)) else: proxy.add_ext( X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement", 1)) proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE", 1)) # does not work (?) seems like need to add authorityCertIssuer # and authorityCertSerialNumber somehow, see rfc 3280 for more # details # try: # subjkey = cert.get_ext('subjectKeyIdentifier') # keyid = "keyid:%s" % subjkey.get_value() # ext = X509.new_extension("authorityKeyIdentifier", keyid, 0) # proxy.add_ext(ext) # except LookupError: # pass else: if globus_bug: proxy.add_ext( X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment", 1)) else: proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE", 1)) proxy.add_ext( X509.new_extension( "keyUsage", "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement", 1)) if not legacy: if full: proxy.add_ext( X509.new_extension("proxyCertInfo", "critical, language:Inherit all", 1)) else: proxy.add_ext( X509.new_extension( "proxyCertInfo", "critical, language:1.3.6.1.4.1.3536.1.1.1.9", 1)) sign_pkey = EVP.PKey() sign_pkey.assign_rsa(key, 0) proxy.sign(sign_pkey, args.get('hash_algorithm', 'sha1')) return X509.load_cert_string(proxy.as_pem())
def generate_proxy(certificate, proxykey=None, full=True, lifetime=43200, extensions=[]): """ generate a new proxy certificate :param certificate: the parent certificate :param proxykey: the key used to sign the proxy :param full: whether this is a full proxy or not """ _certificate = certificate _full = full _proxy, _key = generate_certificate(key=proxykey) _proxy.set_version(2) # generate serial message_digest = EVP.MessageDigest('sha1') pubkey = _proxy.get_pubkey() der_encoding = pubkey.as_der() message_digest.update(der_encoding) digest = message_digest.final() digest_tuple = struct.unpack('BBBB', digest[:4]) sub_hash = long(digest_tuple[0] + (digest_tuple[1] + (digest_tuple[2] + (digest_tuple[3] >> 1) * 256) * 256) * 256) _proxy.set_serial_number(sub_hash) # set issuer issuer = _certificate.get_subject() # set subject subject = X509.X509_Name() for n in issuer: m2.x509_name_add_entry(subject.x509_name, n.x509_name_entry, -1, 0) subject.add_entry_by_txt(field='CN', type=MBSTRING_ASC, entry=str(_proxy.get_serial_number()), len=-1, loc=-1, set=0) _proxy.set_subject_name(subject) # set times not_before = ASN1.ASN1_UTCTIME() not_after = ASN1.ASN1_UTCTIME() not_before.set_time(int(time.time()) - 300) not_after.set_time(int(time.time()) + lifetime) _proxy.set_not_before(not_before) _proxy.set_not_after(not_after) _proxy.set_issuer_name(_certificate.get_subject()) # add extensions try: key_usage = _certificate.get_ext('keyUsage') except LookupError: pass else: r = [] for v in key_usage.get_value().split(', '): if v in ['Non Repudiation', 'keyCertSign']: continue r.append(v) if 'Digital Signature' not in r: r.append('Digital Signature') key_usage_value = ', '.join(r) extensions.append({'name': key_usage.get_name(), 'critical': key_usage.get_critical(), 'value': key_usage_value}) if _full: extensions.append({'name': "proxyCertInfo", 'value': PCI_VALUE_FULL, 'critical': 1}) else: extensions.append({'name': "proxyCertInfo", 'value': PCI_VALUE_LIMITED, 'critical': 1}) if extensions: sslower = lambda s: s.lower().replace(' ', '') for e in extensions: name = e['name'] key = sslower(name) critical = e['critical'] if key in multi_attrs: e['value'] = ', '.join([multi_attrs[key][sslower(v)] for v in e['value'].split(',')]) _proxy.add_ext(X509.new_extension(Att_map[key], e['value'], critical=int(critical))) return _proxy, _key
def _sign_request(self, x509_request, lifetime): not_before = ASN1.ASN1_UTCTIME() not_before.set_datetime(datetime.now(UTC)) not_after = ASN1.ASN1_UTCTIME() not_after.set_datetime(datetime.now(UTC) + lifetime) proxy_subject = X509.X509_Name() for entry in self.context.x509.get_subject(): ret = m2.x509_name_add_entry(proxy_subject._ptr(), entry._ptr(), -1, 0) if ret == 0: raise Exception( "%s: '%s'" % (m2.err_reason_error_string(m2.err_get_error()), entry) ) proxy = X509.X509() proxy.set_serial_number(self.context.x509.get_serial_number()) proxy.set_version(x509_request.get_version()) proxy.set_issuer(self.context.x509.get_subject()) proxy.set_pubkey(x509_request.get_pubkey()) # Extensions are broken in SL5!! if _m2crypto_extensions_broken(): log.warning("X509v3 extensions disabled!") else: # X509v3 Basic Constraints proxy.add_ext(X509.new_extension('basicConstraints', 'CA:FALSE', critical=True)) # X509v3 Key Usage proxy.add_ext(X509.new_extension('keyUsage', 'Digital Signature, Key Encipherment', critical=True)) #X509v3 Authority Key Identifier identifier_ext = _workaround_new_extension( 'authorityKeyIdentifier', 'keyid', critical=False, issuer=self.context.x509 ) proxy.add_ext(identifier_ext) any_rfc_proxies = False # FTS-1217 Ignore the user input and select the min proxy lifetime available on the list min_cert_lifetime = self.context.x509_list[0].get_not_after() for cert in self.context.x509_list: if cert.get_not_after().get_datetime() < min_cert_lifetime.get_datetime(): not_after = cert.get_not_after() min_cert_lifetime = cert.get_not_after() try: cert.get_ext('proxyCertInfo') any_rfc_proxies = True except: pass proxy.set_not_after(not_after) proxy.set_not_before(not_before) if any_rfc_proxies: if _m2crypto_extensions_broken(): raise NotImplementedError("X509v3 extensions are disabled, so RFC proxies can not be generated!") else: _add_rfc3820_extensions(proxy) if any_rfc_proxies: m2.x509_name_set_by_nid(proxy_subject._ptr(), X509.X509_Name.nid['commonName'], str(int(time.time()))) else: m2.x509_name_set_by_nid(proxy_subject._ptr(), X509.X509_Name.nid['commonName'], 'proxy') proxy.set_subject(proxy_subject) proxy.set_version(2) proxy.sign(self.context.evp_key, 'sha1') return proxy