~ubuntu-branches/ubuntu/raring/pyca/raring

« back to all changes in this revision

Viewing changes to pylib/openssl/cnf.py

  • Committer: Bazaar Package Importer
  • Author(s): Lars Bahner
  • Date: 2003-12-02 19:39:35 UTC
  • Revision ID: james.westby@ubuntu.com-20031202193935-fzzt289mntvy6a8q
Tags: upstream-20031118
Import upstream version 20031118

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#######################################################################
 
2
# openssl.cnf.py
 
3
# (c) by Michael Stroeder, michael.stroeder@propack-data.de
 
4
########################################################################
 
5
# Modul fuer den Zugriff auf die SSLeay-Konfigurationsdatei
 
6
# openssl.cnf
 
7
########################################################################
 
8
 
 
9
########################################################################
 
10
# Ab hier gibt es nix mehr zu konfigurieren
 
11
########################################################################
 
12
 
 
13
import sys,types,string,re,charset
 
14
 
 
15
__version__ = '0.6.6'
 
16
 
 
17
########################################################################
 
18
# Funktion GetAllSections() 
 
19
# Eingabe:
 
20
#   keine
 
21
# Ausgabe:
 
22
#   Dictionary mit Abschnittsnamen als Index und Dictionaries der
 
23
#   einzelnen Abschnitte als Feldelemente
 
24
#   {}, falls Konfigurationsdatei leer
 
25
# Anmerkung:
 
26
#   Fuer Konfigurationseintraege ausserhalb eines Abschnittes wird der
 
27
#   Pseudo-Abschnittsnamen '_' gesetzt.
 
28
########################################################################
 
29
 
 
30
def GetAllSections(filename):
 
31
 
 
32
  keys = {'_':[]}
 
33
  result = {'_':{}}
 
34
 
 
35
  # parameters not within a section will be stored in dummy section "_"
 
36
  section_name = '_'
 
37
 
 
38
  # regular exp for a line defining a section name
 
39
  issection_re=re.compile(r'^\s*\[\s*\w+\s*\]\s*(#)*.*')
 
40
 
 
41
  # regular exp for extracting a section name in a section line
 
42
  section_name_re=re.compile(r'\[\s*\w+\s*\]')
 
43
 
 
44
  # regular exp for a syntactically correct line defining a parameter
 
45
  # e.g. name = "parameter1",parameter2 # comment
 
46
  isparamline_re=re.compile(r'^(\d+.)*[\w_]+\s*=.*[\s#]*.*')
 
47
 
 
48
  # regular exp for extracting a parameter [num.]name in a parameter line
 
49
  paramline_numname_re=re.compile(r'(\d+.)*[\w_]+')
 
50
 
 
51
  # regular exp for extracting all parameter values from value incl. comment part
 
52
  onevalue_regex = r'(�.*?�|".*?"|[^:^,^#]*[^:^,^#^\s]|[^:^,^#]+:([^:^,^#]*[^:^,^#^\s]+|".*?"|�.*?�))'
 
53
  paramline_valuepart_re=re.compile(onevalue_regex+r'+(,'+onevalue_regex+')*\s*(#)*')
 
54
 
 
55
  # regular exp for splitting all values from value part
 
56
  paramline_valuesplit_re=re.compile('%s' % (onevalue_regex))
 
57
 
 
58
  # regular exp for testing if param is quoted
 
59
  isquoted_re=re.compile('(%s|%s|%s)' % ('�.*�','".*"',"'.*'"))
 
60
  
 
61
  # Open config file
 
62
  cnf_file = open(filename,'r')
 
63
 
 
64
  # Read first line from file
 
65
  line = cnf_file.readline()
 
66
  linenum = 0
 
67
  while line:
 
68
  
 
69
    line = string.strip(line)
 
70
#    sys.stderr.write('***%s\n' % (line))
 
71
    if issection_re.search(line)!=None:
 
72
 
 
73
      # Section found => new section in result dict
 
74
 
 
75
      # extract plain section name by searching [ aphanum-string ]
 
76
      # and stripping "[", "]" and white-spaces
 
77
      section_name = string.strip(section_name_re.search(line).group(0)[1:-1])
 
78
      # Create new sub-dict. If there are multiple sections (broken cnf-file)
 
79
      # with the same name, the last one is valid.
 
80
      keys[section_name]=[]
 
81
      result[section_name]={}
 
82
 
 
83
    elif isparamline_re.search(line)!=None:
 
84
 
 
85
      # Is valid parameter line
 
86
 
 
87
      # Extract parameter name
 
88
      name = paramline_numname_re.search(line).group(0)
 
89
      # Extract parameter num.name
 
90
      try:
 
91
        num,name = string.split(name,'.',1)
 
92
      except ValueError:
 
93
        num = ''
 
94
      
 
95
      # extract plain value part
 
96
      # and strip "=", "#" and white-spaces
 
97
      line = string.strip(line[string.index(line,'=')+1:])
 
98
      if line:
 
99
        valuepart = string.strip(paramline_valuepart_re.match(line).group(0))
 
100
        valuegroups = paramline_valuesplit_re.findall(valuepart)
 
101
      else:
 
102
        valuepart = ''
 
103
        valuegroups = []
 
104
 
 
105
#      sys.stderr.write('***valuegroups=%s\n' % (valuegroups))
 
106
      if len(valuegroups)>1:
 
107
        result[section_name][name] = []
 
108
        for valuetuple in valuegroups:
 
109
          if isquoted_re.search(valuetuple[0]):
 
110
            value = valuetuple[0][1:-1]
 
111
          else:
 
112
            value = valuetuple[0]
 
113
          # New entry in current section
 
114
          keys[section_name].append(name)
 
115
          # Store value of entry in dict
 
116
          value = string.strip(value)
 
117
          if value:
 
118
            result[section_name][name].append(value)
 
119
      elif len(valuegroups)==1:
 
120
        valuetuple = valuegroups[0]
 
121
        if isquoted_re.search(valuetuple[0]):
 
122
          value = valuetuple[0][1:-1]
 
123
        else:
 
124
          value = valuetuple[0]
 
125
        # New entry in current section
 
126
        keys[section_name].append(name)
 
127
        # Store value of entry in dict
 
128
        result[section_name][name] = string.strip(value)
 
129
 
 
130
    # Read next line from file
 
131
    line = cnf_file.readline()
 
132
    linenum = linenum+1
 
133
 
 
134
  cnf_file.close()
 
135
 
 
136
  return keys,result
 
137
 
 
138
########################################################################
 
139
# Objektklasse fuer eine CA-Definition
 
140
########################################################################
 
141
 
 
142
class caDataClass:
 
143
 
 
144
  def __init__(self):
 
145
    pass
 
146
 
 
147
  # returns 1 if the certificates of CA ca_name are
 
148
  # client certificates (depending on keyUsage and nsCertType).
 
149
  def isclientcert(self):
 
150
    if self.basicConstraints and self.basicConstraints=='CA:true':
 
151
      return 0
 
152
    if self.nsCertType:
 
153
      if type(self.nsCertType)==types.ListType:
 
154
        isClientCert=0
 
155
        for i in self.nsCertType:
 
156
          isClientCert = isClientCert or (i in ['email','client','objsign'])
 
157
      else:
 
158
        isClientCert = self.nsCertType in ['email','client','objsign']
 
159
      return isClientCert
 
160
    else:
 
161
      return 1
 
162
    
 
163
  # returns 1 if the certificates of CA ca_name are usable for
 
164
  # email (depending on keyUsage and nsCertType).
 
165
  def isemailcert(self):
 
166
    if self.basicConstraints and self.basicConstraints=='CA:true':
 
167
      return 0
 
168
    return (type(self.nsCertType)==types.ListType and ('email' in self.nsCertType)) or \
 
169
           (self.nsCertType=='email') or \
 
170
           (self.nsCertType=='')
 
171
 
 
172
  # returns 1 if the certificates of CA ca_name are usable for
 
173
  # email (depending on keyUsage and nsCertType).
 
174
  def isservercert(self):
 
175
    if self.basicConstraints and self.basicConstraints=='CA:true':
 
176
      return 0
 
177
    return (type(self.nsCertType)==types.ListType and ('server' in self.nsCertType)) or \
 
178
           (self.nsCertType=='server') or \
 
179
           (self.nsCertType=='')
 
180
 
 
181
########################################################################
 
182
# Objektklasse fuer eine Konfigurationsdatei
 
183
########################################################################
 
184
 
 
185
class OpenSSLConfigClass:
 
186
 
 
187
  def __init__(self,pathname):
 
188
    self.sectionkeys,self.data = GetAllSections(pathname)
 
189
 
 
190
  # FIX ME!!! Look for Netscape specs about key usage determination.
 
191
 
 
192
  # Build tree with CA hierarchy
 
193
  def getcatree(self):
 
194
    catree = {'.':[]}
 
195
    ca_names = self.sectionkeys.get('ca',[])
 
196
    for ca_name in ca_names:
 
197
      signedby = self.data[self.data['ca'][ca_name]].get('signedby','')
 
198
      if signedby:
 
199
        if catree.has_key(signedby):
 
200
          catree[signedby].append(ca_name)
 
201
        else:
 
202
          catree[signedby]=[ca_name]
 
203
      else:
 
204
        catree['.'].append(ca_name)
 
205
    return catree
 
206
 
 
207
  # Get all relevant data of a CA definition and its subsequent sections
 
208
  def getcadata(self,ca_name):
 
209
    ca = caDataClass()
 
210
    pyca_section = self.data.get('pyca',{})
 
211
    ca.sectionname = self.data['ca'][ca_name]
 
212
    ca_section = self.data[ca.sectionname]
 
213
    ca.name = ca_name
 
214
    ca.dir = ca_section.get('dir','')
 
215
    ca.serial = string.replace(ca_section.get('serial','$dir/serial'),'$dir',ca.dir)
 
216
    ca.certificate = string.replace(ca_section.get('certificate','$dir/cacert.pem'),'$dir',ca.dir)
 
217
    ca.private_key = string.replace(ca_section.get('private_key','$dir/private/cakey.pem'),'$dir',ca.dir)
 
218
    ca.database = string.replace(ca_section.get('database','$dir/index.txt'),'$dir',ca.dir)
 
219
    ca.pend_reqs_dir = string.replace(ca_section.get('pend_reqs_dir','$dir/pendreqs'),'$dir',ca.dir)
 
220
    ca.crl = string.replace(ca_section.get('crl','$dir/crl.pem'),'$dir',ca.dir)
 
221
    ca.crl_dir = string.replace(ca_section.get('crl_dir','$dir/crl'),'$dir',ca.dir)
 
222
    ca.new_reqs_dir = string.replace(ca_section.get('new_reqs_dir','$dir/newreqs'),'$dir',ca.dir)
 
223
    ca.old_reqs_dir = string.replace(ca_section.get('old_reqs_dir','$dir/oldreqs'),'$dir',ca.dir)
 
224
    ca.new_certs_dir = string.replace(ca_section.get('new_certs_dir','$dir/newcerts'),'$dir',ca.dir)
 
225
    ca.certs = string.replace(ca_section.get('certs','$dir/certs'),'$dir',ca.dir)
 
226
    ca.req = ca_section.get('req','req')
 
227
    ca.policy = ca_section.get('policy','')
 
228
    ca.signedby = ca_section.get('signedby','')
 
229
    ca.ca_reqfile = ca_section.get('ca_reqfile','')
 
230
    ca.ca_x509_extfile = ca_section.get('ca_x509_extfile','')
 
231
    ca.min_key_size = string.atoi(ca_section.get('min_key_size','0'))
 
232
    ca.default_days = string.atoi(ca_section.get('default_days','0'))
 
233
    ca.crl_days = string.atoi(ca_section.get('crl_days','0'))
 
234
    ca.crl_treshold = string.atoi(ca_section.get('crl_treshold','0'))
 
235
 
 
236
    ca.x509_extensions = ca_section.get('x509_extensions','')
 
237
    x509_extensions_section = self.data.get(ca.x509_extensions,{})
 
238
 
 
239
    # PKIX attributes
 
240
    ca.basicConstraints = x509_extensions_section.get('basicConstraints','')
 
241
    ca.keyUsage = x509_extensions_section.get('keyUsage','')
 
242
    ca.extendedKeyUsage = x509_extensions_section.get('extendedKeyUsage','')
 
243
 
 
244
    # Netscape attributes
 
245
    ca.nsCertType = x509_extensions_section.get('nsCertType','')
 
246
    ca.nsBaseUrl = x509_extensions_section.get('nsBaseUrl',pyca_section.get('nsBaseUrl',''))
 
247
    ca.nsCaRevocationUrl = x509_extensions_section.get('nsCaRevocationUrl','')
 
248
    ca.nsRevocationUrl = x509_extensions_section.get('nsRevocationUrl','')
 
249
    ca.nsCaPolicyUrl = x509_extensions_section.get('nsCaPolicyUrl','')
 
250
    ca.nsComment = x509_extensions_section.get('nsComment','')
 
251
    if type(ca.nsCertType)==types.ListType:
 
252
      ca.nsCertTypeStr=string.join(ca.nsCertType,'/')
 
253
    else:
 
254
      ca.nsCertTypeStr=ca.nsCertType
 
255
 
 
256
    return ca
 
257
 
 
258
  # get list of pathnames of all intermediate CA certficates
 
259
  # excluding the self-signed root CA cert
 
260
  def getcacertchain(self,ca_name):
 
261
    ca_section = self.data[self.data['ca'][ca_name]]
 
262
    result = []
 
263
    while ca_section.has_key('signedby'):
 
264
      ca_dir = ca_section.get('dir','')
 
265
      ca_certificate = string.replace(ca_section.get('certificate','$dir/cacert.pem'),'$dir',ca_dir)
 
266
      result.append(ca_certificate)
 
267
      ca_signedby = ca_section['signedby']
 
268
      if not self.data['ca'].has_key(ca_signedby):
 
269
        raise KeyError,'CA name not found'
 
270
      ca_section = self.data[self.data['ca'][ca_signedby]]
 
271
    return result