From fcf6a1e77c29d0eda113ed75e28941e2b2800068 Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Wed, 16 Oct 2013 07:41:23 +0000 Subject: Add function for parsing friendly name from certificate requests. Reviewed-By: Petr Viktorin --- ipalib/pkcs10.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'ipalib/pkcs10.py') diff --git a/ipalib/pkcs10.py b/ipalib/pkcs10.py index 12db78377..5958d5a21 100644 --- a/ipalib/pkcs10.py +++ b/ipalib/pkcs10.py @@ -21,6 +21,8 @@ import os import sys import base64 import nss.nss as nss +from pyasn1.type import univ, namedtype, tag +from pyasn1.codec.der import decoder from ipapython import ipautil from ipalib import api @@ -54,6 +56,53 @@ def get_subjectaltname(csr, datatype=PEM): del request return None +# Unfortunately, NSS can only parse the extension request attribute, so +# we have to parse friendly name ourselves (see RFC 2986) +class _Attribute(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('type', univ.ObjectIdentifier()), + namedtype.NamedType('values', univ.Set()), + ) + +class _Attributes(univ.SetOf): + componentType = _Attribute() + +class _CertificationRequestInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer()), + namedtype.NamedType('subject', univ.Sequence()), + namedtype.NamedType('subjectPublicKeyInfo', univ.Sequence()), + namedtype.OptionalNamedType('attributes', _Attributes().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + +class _CertificationRequest(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('certificationRequestInfo', + _CertificationRequestInfo()), + namedtype.NamedType('signatureAlgorithm', univ.Sequence()), + namedtype.NamedType('signatureValue', univ.BitString()), + ) + +_FRIENDLYNAME = univ.ObjectIdentifier('1.2.840.113549.1.9.20') + +def get_friendlyname(csr, datatype=PEM): + """ + Given a CSR return the value of the friendlyname attribute, if any. + + The return value is a string. + """ + if datatype == PEM: + csr = strip_header(csr) + csr = base64.b64decode(csr) + + csr = decoder.decode(csr, asn1Spec=_CertificationRequest())[0] + for attribute in csr['certificationRequestInfo']['attributes']: + if attribute['type'] == _FRIENDLYNAME: + return unicode(attribute['values'][0]) + + return None + def strip_header(csr): """ Remove the header and footer from a CSR. @@ -96,3 +145,4 @@ if __name__ == '__main__': print load_certificate_request(csr) print get_subject(csr) print get_subjectaltname(csr) + print get_friendlyname(csr) -- cgit