Package contrail ::
Package security ::
Package onlineca ::
Package client ::
Module openssl_utils
|
|
1 """Online CA OpenSSL utilities module
2
3 Contrail Project
4 """
5 __author__ = "P J Kershaw"
6 __date__ = "24/09/12"
7 __copyright__ = "(C) 2012 Science and Technology Facilities Council"
8 __license__ = "BSD - see LICENSE file in top-level directory"
9 __contact__ = "Philip.Kershaw@stfc.ac.uk"
10 __revision__ = '$Id$'
11 import re
12
13 from OpenSSL import crypto
17 '''Base class for X509SubjectName class errors'''
18
21 '''Parsing error for X509SubjectName class'''
22
25 '''Configuration related error for X509SubjectName class'''
26
29 '''Class to handle X.509 subject names'''
30 SHORT_NAME_LOOKUP = {
31 'commonName': 'CN',
32 'organisationalUnitName': 'OU',
33 'organisation': 'O',
34 'countryName': 'C',
35 'emailAddress': 'EMAILADDRESS',
36 'localityName': 'L',
37 'stateOrProvinceName': 'ST',
38 'streetAddress': 'STREET',
39 'domainComponent': 'DC',
40 'userid': 'UID'
41 }
42 SLASH_PARSER_RE_STR = '/(%s)=' % '|'.join(SHORT_NAME_LOOKUP.keys() +
43 SHORT_NAME_LOOKUP.values())
44 SLASH_PARSER_RE = re.compile(SLASH_PARSER_RE_STR)
45
46 COMMA_PARSER_RE_STR = '[,]?\s*(%s)=' % '|'.join(SHORT_NAME_LOOKUP.keys() +
47 SHORT_NAME_LOOKUP.values())
48 COMMA_PARSER_RE = re.compile(COMMA_PARSER_RE_STR)
49
50 VALID_SEPARATORS = ('/', ',')
51
54
55 @classmethod
57 obj = cls()
58 obj._dn = cls.parse(dn, separator)
59
60 return obj
61
62 @classmethod
63 - def parse(cls, dn, separator=None):
64 '''Parse string distinguished name into a dictionary for fields. Where
65 multiple entries exist for a field, values are set as a tuple
66 '''
67 if separator in ('/', None):
68 parser_re = cls.SLASH_PARSER_RE
69 elif separator == ',':
70 parser_re = cls.COMMA_PARSER_RE
71 else:
72 raise X509SubjectNameConfigError('Invalid field separator %r' %
73 separator)
74
75 dn_fields = parser_re.split(dn)
76 if len(dn_fields) < 2:
77 raise X509SubjectNameConfigError('Error parsing DN string: \"%s\"' %
78 dn)
79
80 items = zip(dn_fields[1::2], dn_fields[2::2])
81
82
83
84 parsed_dn = {}
85 for key, val in items:
86 key = key.strip()
87 if key in parsed_dn:
88 if isinstance(parsed_dn[key], tuple):
89 parsed_dn[key] = tuple(list(parsed_dn[key]) + [val])
90 else:
91 parsed_dn[key] = (parsed_dn[key], val)
92 else:
93 parsed_dn[key] = val
94
95 return parsed_dn
96
98 '''Serialize subject name iterable into a string'''
99 return self.__class__.Serialize(self._dn, *args, **kwargs)
100
101 @classmethod
102 - def Serialize(cls, dn, separator='/', sort=True):
103 '''Classmethod implementation - Serialize subject name iterable into a
104 string'''
105
106 if separator not in cls.VALID_SEPARATORS:
107 raise X509SubjectNameConfigError('Invalid field separator %r' %
108 separator)
109
110
111 if separator == '/':
112 s_dn = separator
113 else:
114 s_dn = ''
115
116 dn_list = []
117 for key, val in dn.items():
118 if val:
119 if isinstance(val, tuple):
120 kv_pairs = ["%s=%s" % (key, val_sub) for val_sub in val]
121 dn_list += [separator.join(kv_pairs)]
122 else:
123 dn_list += ["%s=%s" % (key, val)]
124
125 if sort:
126 dn_list.sort()
127
128 s_dn += separator.join(dn_list)
129
130 return s_dn
131
133 '''@return: this object as an OpenSSL package equivalent type
134 @rtype: OpenSSL.crypto.X509Name
135 '''
136 subject_name = crypto.X509().get_subject()
137 for k, v in self._dn.items():
138 if isinstance(v, tuple):
139
140
141
142 _v = v[0] + '/' + '/'.join(["%s=%s" % (k, i) for i in v[1:]])
143 setattr(subject_name, k, _v)
144 else:
145 setattr(subject_name, k, v)
146
147 return subject_name
148