Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: third_party/twisted_8_1/twisted/internet/_sslverify.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_sslverify -*-
2 # Copyright 2005 Divmod, Inc. See LICENSE file for details
3
4 import hashlib
5 import itertools
6 from OpenSSL import SSL, crypto
7
8 from twisted.python import reflect, util
9 from twisted.internet.defer import Deferred
10 from twisted.internet.error import VerifyError, CertificateError
11
12 # Private - shared between all OpenSSLCertificateOptions, counts up to provide
13 # a unique session id for each context
14 _sessionCounter = itertools.count().next
15
16 class _SSLApplicationData(object):
17 def __init__(self):
18 self.problems = []
19
20 class OpenSSLVerifyError(VerifyError):
21
22 _errorCodes = {0: ('X509_V_OK',
23 'ok',
24 'the operation was successful. >'),
25
26 2: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT',
27 'unable to get issuer certificate',
28 "The issuer certificate could not be found. This "
29 "occurs if the issuer certificate of an untrusted "
30 "certificate cannot be found."),
31
32 3: ('X509_V_ERR_UNABLE_TO_GET_CRL',
33 'unable to get certificate CRL',
34 "The CRL of a certificate could not be found. "
35 "Unused."),
36
37 4: ('X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE',
38 "unable to decrypt certificate's signature",
39 "The certificate signature could not be decrypted. "
40 "This means that the actual signature value could not "
41 "be determined rather than it not matching the "
42 "expected value, this is only meaningful for RSA "
43 "keys."),
44
45 5: ('X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE',
46 "unable to decrypt CRL's signature",
47 "The CRL signature could not be decrypted. This "
48 "means that the actual signature value could not be "
49 "determined rather than it not matching the expected "
50 "value. Unused."),
51
52 6: ('X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY',
53 'unable to decode issuer',
54 "Public key the public key in the certificate "
55 "SubjectPublicKeyInfo could not be read."),
56
57 7: ('X509_V_ERR_CERT_SIGNATURE_FAILURE',
58 'certificate signature failure',
59 'The signature of the certificate is invalid.'),
60
61 8: ('X509_V_ERR_CRL_SIGNATURE_FAILURE',
62 'CRL signature failure',
63 'The signature of the certificate is invalid. Unused.'),
64
65 9: ('X509_V_ERR_CERT_NOT_YET_VALID',
66 'certificate is not yet valid',
67 "The certificate is not yet valid. The notBefore "
68 "date is after the current time."),
69
70 10: ('X509_V_ERR_CERT_HAS_EXPIRED',
71 'certificate has expired',
72 "The certificate has expired. The notAfter date "
73 "is before the current time."),
74
75 11: ('X509_V_ERR_CRL_NOT_YET_VALID',
76 'CRL is not yet valid',
77 'The CRL is not yet valid. Unused.'),
78
79 12: ('X509_V_ERR_CRL_HAS_EXPIRED',
80 'CRL has expired',
81 'The CRL has expired. Unused.'),
82
83 13: ('X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD',
84 "format error in certificate's notBefore field",
85 "The certificate's notBefore field contains an "
86 "invalid time."),
87
88 14: ('X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD',
89 "format error in certificate's notAfter field.",
90 "The certificate's notAfter field contains an "
91 "invalid time."),
92
93 15: ('X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD',
94 "format error in CRL's lastUpdate field",
95 "The CRL lastUpdate field contains an invalid "
96 "time. Unused."),
97
98 16: ('X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD',
99 "format error in CRL's nextUpdate field",
100 "The CRL nextUpdate field contains an invalid "
101 "time. Unused."),
102
103 17: ('X509_V_ERR_OUT_OF_MEM',
104 'out of memory',
105 'An error occurred trying to allocate memory. '
106 'This should never happen.'),
107
108 18: ('X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT',
109 'self signed certificate',
110 'The passed certificate is self signed and the same '
111 'certificate cannot be found in the list of trusted '
112 'certificates.'),
113
114 19: ('X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN',
115 'self signed certificate in certificate chain',
116 'The certificate chain could be built up using the '
117 'untrusted certificates but the root could not be '
118 'found locally.'),
119
120 20: ('X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
121 'unable to get local issuer certificate',
122 'The issuer certificate of a locally looked up '
123 'certificate could not be found. This normally '
124 'means the list of trusted certificates is not '
125 'complete.'),
126
127 21: ('X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE',
128 'unable to verify the first certificate',
129 'No signatures could be verified because the chain '
130 'contains only one certificate and it is not self '
131 'signed.'),
132
133 22: ('X509_V_ERR_CERT_CHAIN_TOO_LONG',
134 'certificate chain too long',
135 'The certificate chain length is greater than the '
136 'supplied maximum depth. Unused.'),
137
138 23: ('X509_V_ERR_CERT_REVOKED',
139 'certificate revoked',
140 'The certificate has been revoked. Unused.'),
141
142 24: ('X509_V_ERR_INVALID_CA',
143 'invalid CA certificate',
144 'A CA certificate is invalid. Either it is not a CA '
145 'or its extensions are not consistent with the '
146 'supplied purpose.'),
147
148 25: ('X509_V_ERR_PATH_LENGTH_EXCEEDED',
149 'path length constraint exceeded',
150 'The basicConstraints pathlength parameter has been '
151 'exceeded.'),
152
153 26: ('X509_V_ERR_INVALID_PURPOSE',
154 'unsupported certificate purpose',
155 'The supplied certificate cannot be used for the '
156 'specified purpose.'),
157
158 27: ('X509_V_ERR_CERT_UNTRUSTED',
159 'certificate not trusted',
160 'The root CA is not marked as trusted for the '
161 'specified purpose.'),
162
163 28: ('X509_V_ERR_CERT_REJECTED',
164 'certificate rejected',
165 'The root CA is marked to reject the specified '
166 'purpose.'),
167
168 29: ('X509_V_ERR_SUBJECT_ISSUER_MISMATCH',
169 'subject issuer mismatch',
170 'The current candidate issuer certificate was '
171 'rejected because its subject name did not match '
172 'the issuer name of the current certificate. Only '
173 'displayed when the issuer_checks option is set.'),
174
175 30: ('X509_V_ERR_AKID_SKID_MISMATCH',
176 'authority and subject key identifier mismatch',
177 'The current candidate issuer certificate was '
178 'rejected because its subject key identifier was '
179 'present and did not match the authority key '
180 'identifier current certificate. Only displayed '
181 'when the issuer_checks option is set.'),
182
183 31: ('X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH',
184 'authority and issuer serial number mismatch',
185 'The current candidate issuer certificate was '
186 'rejected because its issuer name and serial '
187 'number was present and did not match the '
188 'authority key identifier of the current '
189 'certificate. Only displayed when the issuer_checks '
190 'option is set.'),
191
192 32: ('X509_V_ERR_KEYUSAGE_NO_CERTSIGN',
193 'key usage does not include certificate',
194 'Signing the current candidate issuer certificate was '
195 'rejected because its keyUsage extension does not '
196 'permit certificate signing.'),
197
198 50: ('X509_V_ERR_APPLICATION_VERIFICATION',
199 'application verification failure',
200 'an application specific error. Unused.')}
201
202
203 def __init__(self, cert, errno, depth):
204 VerifyError.__init__(self, cert, errno, depth)
205 self.cert = cert
206 self.errno = errno
207 self.depth = depth
208
209 def __repr__(self):
210 x = self._errorCodes.get(self.errno)
211 if x is not None:
212 name, short, long = x
213 return 'Peer Certificate Verification Failed: %s (error code: %d)' % (
214 long, self.errno
215 )
216 return "Peer Certificate Verification Failed for Unknown Reason"
217
218 __str__ = __repr__
219
220
221 _x509names = {
222 'CN': 'commonName',
223 'commonName': 'commonName',
224
225 'O': 'organizationName',
226 'organizationName': 'organizationName',
227
228 'OU': 'organizationalUnitName',
229 'organizationalUnitName': 'organizationalUnitName',
230
231 'L': 'localityName',
232 'localityName': 'localityName',
233
234 'ST': 'stateOrProvinceName',
235 'stateOrProvinceName': 'stateOrProvinceName',
236
237 'C': 'countryName',
238 'countryName': 'countryName',
239
240 'emailAddress': 'emailAddress'}
241
242
243 class DistinguishedName(dict):
244 """
245 Identify and describe an entity.
246
247 Distinguished names are used to provide a minimal amount of identifying
248 information about a certificate issuer or subject. They are commonly
249 created with one or more of the following fields::
250
251 commonName (CN)
252 organizationName (O)
253 organizationalUnitName (OU)
254 localityName (L)
255 stateOrProvinceName (ST)
256 countryName (C)
257 emailAddress
258 """
259 __slots__ = ()
260
261 def __init__(self, **kw):
262 for k, v in kw.iteritems():
263 setattr(self, k, v)
264
265
266 def _copyFrom(self, x509name):
267 d = {}
268 for name in _x509names:
269 value = getattr(x509name, name, None)
270 if value is not None:
271 setattr(self, name, value)
272
273
274 def _copyInto(self, x509name):
275 for k, v in self.iteritems():
276 setattr(x509name, k, v)
277
278
279 def __repr__(self):
280 return '<DN %s>' % (dict.__repr__(self)[1:-1])
281
282
283 def __getattr__(self, attr):
284 try:
285 return self[_x509names[attr]]
286 except KeyError:
287 raise AttributeError(attr)
288
289
290 def __setattr__(self, attr, value):
291 assert type(attr) is str
292 if not attr in _x509names:
293 raise AttributeError("%s is not a valid OpenSSL X509 name field" % ( attr,))
294 realAttr = _x509names[attr]
295 value = value.encode('ascii')
296 assert type(value) is str
297 self[realAttr] = value
298
299
300 def inspect(self):
301 """
302 Return a multi-line, human-readable representation of this DN.
303 """
304 l = []
305 lablen = 0
306 def uniqueValues(mapping):
307 return dict.fromkeys(mapping.itervalues()).keys()
308 for k in uniqueValues(_x509names):
309 label = util.nameToLabel(k)
310 lablen = max(len(label), lablen)
311 v = getattr(self, k, None)
312 if v is not None:
313 l.append((label, v))
314 lablen += 2
315 for n, (label, attr) in enumerate(l):
316 l[n] = (label.rjust(lablen)+': '+ attr)
317 return '\n'.join(l)
318
319 DN = DistinguishedName
320
321
322 class CertBase:
323 def __init__(self, original):
324 self.original = original
325
326 def _copyName(self, suffix):
327 dn = DistinguishedName()
328 dn._copyFrom(getattr(self.original, 'get_'+suffix)())
329 return dn
330
331 def getSubject(self):
332 """
333 Retrieve the subject of this certificate.
334
335 @rtype: L{DistinguishedName}
336 @return: A copy of the subject of this certificate.
337 """
338 return self._copyName('subject')
339
340
341
342 def problemsFromTransport(tpt):
343 """
344 Retrieve the SSL errors associated with the given transport.
345
346 @type tpt: L{ISystemHandle} provider wrapper around an SSL connection.
347 @rtype: C{list} of L{OpenSSLVerifyError}.
348 """
349 return tpt.getHandle().get_context().get_app_data().problems
350
351
352 def _handleattrhelper(Class, transport, methodName):
353 """
354 (private) Helper for L{Certificate.peerFromTransport} and
355 L{Certificate.hostFromTransport} which checks for incompatible handle types
356 and null certificates and raises the appropriate exception or returns the
357 appropriate certificate object.
358 """
359 method = getattr(transport.getHandle(),
360 "get_%s_certificate" % (methodName,), None)
361 if method is None:
362 raise CertificateError(
363 "non-TLS transport %r did not have %s certificate" % (transport, met hodName))
364 cert = method()
365 if cert is None:
366 raise CertificateError(
367 "TLS transport %r did not have %s certificate" % (transport, methodN ame))
368 return Class(cert)
369
370
371 class Certificate(CertBase):
372 """
373 An x509 certificate.
374 """
375 def __repr__(self):
376 return '<%s Subject=%s Issuer=%s>' % (self.__class__.__name__,
377 self.getSubject().commonName,
378 self.getIssuer().commonName)
379
380 def __eq__(self, other):
381 if isinstance(other, Certificate):
382 return self.dump() == other.dump()
383 return False
384
385
386 def __ne__(self, other):
387 return not self.__eq__(other)
388
389
390 def load(Class, requestData, format=crypto.FILETYPE_ASN1, args=()):
391 """
392 Load a certificate from an ASN.1- or PEM-format string.
393
394 @rtype: C{Class}
395 """
396 return Class(crypto.load_certificate(format, requestData), *args)
397 load = classmethod(load)
398 _load = load
399
400
401 def dumpPEM(self):
402 """
403 Dump this certificate to a PEM-format data string.
404
405 @rtype: C{str}
406 """
407 return self.dump(crypto.FILETYPE_PEM)
408
409
410 def loadPEM(Class, data):
411 """
412 Load a certificate from a PEM-format data string.
413
414 @rtype: C{Class}
415 """
416 return Class.load(data, crypto.FILETYPE_PEM)
417 loadPEM = classmethod(loadPEM)
418
419
420 def peerFromTransport(Class, transport):
421 """
422 Get the certificate for the remote end of the given transport.
423
424 @type: L{ISystemHandle}
425 @rtype: C{Class}
426
427 @raise: L{CertificateError}, if the given transport does not have a peer
428 certificate.
429 """
430 return _handleattrhelper(Class, transport, 'peer')
431 peerFromTransport = classmethod(peerFromTransport)
432
433
434 def hostFromTransport(Class, transport):
435 """
436 Get the certificate for the local end of the given transport.
437
438 @param transport: an L{ISystemHandle} provider; the transport we will
439
440 @rtype: C{Class}
441
442 @raise: L{CertificateError}, if the given transport does not have a host
443 certificate.
444 """
445 return _handleattrhelper(Class, transport, 'host')
446 hostFromTransport = classmethod(hostFromTransport)
447
448
449 def getPublicKey(self):
450 """
451 Get the public key for this certificate.
452
453 @rtype: L{PublicKey}
454 """
455 return PublicKey(self.original.get_pubkey())
456
457
458 def dump(self, format=crypto.FILETYPE_ASN1):
459 return crypto.dump_certificate(format, self.original)
460
461
462 def serialNumber(self):
463 """
464 Retrieve the serial number of this certificate.
465
466 @rtype: C{int}
467 """
468 return self.original.get_serial_number()
469
470
471 def digest(self, method='md5'):
472 """
473 Return a digest hash of this certificate using the specified hash
474 algorithm.
475
476 @param method: One of C{'md5'} or C{'sha'}.
477 @rtype: C{str}
478 """
479 return self.original.digest(method)
480
481
482 def _inspect(self):
483 return '\n'.join(['Certificate For Subject:',
484 self.getSubject().inspect(),
485 '\nIssuer:',
486 self.getIssuer().inspect(),
487 '\nSerial Number: %d' % self.serialNumber(),
488 'Digest: %s' % self.digest()])
489
490
491 def inspect(self):
492 """
493 Return a multi-line, human-readable representation of this
494 Certificate, including information about the subject, issuer, and
495 public key.
496 """
497 return '\n'.join((self._inspect(), self.getPublicKey().inspect()))
498
499
500 def getIssuer(self):
501 """
502 Retrieve the issuer of this certificate.
503
504 @rtype: L{DistinguishedName}
505 @return: A copy of the issuer of this certificate.
506 """
507 return self._copyName('issuer')
508
509
510 def options(self, *authorities):
511 raise NotImplementedError('Possible, but doubtful we need this yet')
512
513
514
515 class CertificateRequest(CertBase):
516 """
517 An x509 certificate request.
518
519 Certificate requests are given to certificate authorities to be signed and
520 returned resulting in an actual certificate.
521 """
522 def load(Class, requestData, requestFormat=crypto.FILETYPE_ASN1):
523 req = crypto.load_certificate_request(requestFormat, requestData)
524 dn = DistinguishedName()
525 dn._copyFrom(req.get_subject())
526 if not req.verify(req.get_pubkey()):
527 raise VerifyError("Can't verify that request for %r is self-signed." % (dn,))
528 return Class(req)
529 load = classmethod(load)
530
531
532 def dump(self, format=crypto.FILETYPE_ASN1):
533 return crypto.dump_certificate_request(format, self.original)
534
535
536
537 class PrivateCertificate(Certificate):
538 """
539 An x509 certificate and private key.
540 """
541 def __repr__(self):
542 return Certificate.__repr__(self) + ' with ' + repr(self.privateKey)
543
544
545 def _setPrivateKey(self, privateKey):
546 if not privateKey.matches(self.getPublicKey()):
547 raise VerifyError(
548 "Sanity check failed: Your certificate was not properly signed." )
549 self.privateKey = privateKey
550 return self
551
552
553 def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
554 """
555 Create a new L{PrivateCertificate} from the given certificate data and
556 this instance's private key.
557 """
558 return self.load(newCertData, self.privateKey, format)
559
560
561 def load(Class, data, privateKey, format=crypto.FILETYPE_ASN1):
562 return Class._load(data, format)._setPrivateKey(privateKey)
563 load = classmethod(load)
564
565
566 def inspect(self):
567 return '\n'.join([Certificate._inspect(self),
568 self.privateKey.inspect()])
569
570
571 def dumpPEM(self):
572 """
573 Dump both public and private parts of a private certificate to
574 PEM-format data.
575 """
576 return self.dump(crypto.FILETYPE_PEM) + self.privateKey.dump(crypto.FILE TYPE_PEM)
577
578
579 def loadPEM(Class, data):
580 """
581 Load both private and public parts of a private certificate from a
582 chunk of PEM-format data.
583 """
584 return Class.load(data, KeyPair.load(data, crypto.FILETYPE_PEM),
585 crypto.FILETYPE_PEM)
586 loadPEM = classmethod(loadPEM)
587
588
589 def fromCertificateAndKeyPair(Class, certificateInstance, privateKey):
590 privcert = Class(certificateInstance.original)
591 return privcert._setPrivateKey(privateKey)
592 fromCertificateAndKeyPair = classmethod(fromCertificateAndKeyPair)
593
594
595 def options(self, *authorities):
596 options = dict(privateKey=self.privateKey.original,
597 certificate=self.original)
598 if authorities:
599 options.update(dict(verify=True,
600 requireCertificate=True,
601 caCerts=[auth.original for auth in authorities]) )
602 return OpenSSLCertificateOptions(**options)
603
604
605 def certificateRequest(self, format=crypto.FILETYPE_ASN1,
606 digestAlgorithm='md5'):
607 return self.privateKey.certificateRequest(
608 self.getSubject(),
609 format,
610 digestAlgorithm)
611
612
613 def signCertificateRequest(self,
614 requestData,
615 verifyDNCallback,
616 serialNumber,
617 requestFormat=crypto.FILETYPE_ASN1,
618 certificateFormat=crypto.FILETYPE_ASN1):
619 issuer = self.getSubject()
620 return self.privateKey.signCertificateRequest(
621 issuer,
622 requestData,
623 verifyDNCallback,
624 serialNumber,
625 requestFormat,
626 certificateFormat)
627
628
629 def signRequestObject(self, certificateRequest, serialNumber,
630 secondsToExpiry=60 * 60 * 24 * 365, # One year
631 digestAlgorithm='md5'):
632 return self.privateKey.signRequestObject(self.getSubject(),
633 certificateRequest,
634 serialNumber,
635 secondsToExpiry,
636 digestAlgorithm)
637
638
639 class PublicKey:
640 def __init__(self, osslpkey):
641 self.original = osslpkey
642 req1 = crypto.X509Req()
643 req1.set_pubkey(osslpkey)
644 self._emptyReq = crypto.dump_certificate_request(crypto.FILETYPE_ASN1, r eq1)
645
646
647 def matches(self, otherKey):
648 return self._emptyReq == otherKey._emptyReq
649
650
651 # XXX This could be a useful method, but sometimes it triggers a segfault,
652 # so we'll steer clear for now.
653 # def verifyCertificate(self, certificate):
654 # """
655 # returns None, or raises a VerifyError exception if the certificate
656 # could not be verified.
657 # """
658 # if not certificate.original.verify(self.original):
659 # raise VerifyError("We didn't sign that certificate.")
660
661 def __repr__(self):
662 return '<%s %s>' % (self.__class__.__name__, self.keyHash())
663
664
665 def keyHash(self):
666 """
667 MD5 hex digest of signature on an empty certificate request with this
668 key.
669 """
670 return hashlib.md5(self._emptyReq).hexdigest()
671
672
673 def inspect(self):
674 return 'Public Key with Hash: %s' % (self.keyHash(),)
675
676
677
678 class KeyPair(PublicKey):
679
680 def load(Class, data, format=crypto.FILETYPE_ASN1):
681 return Class(crypto.load_privatekey(format, data))
682 load = classmethod(load)
683
684
685 def dump(self, format=crypto.FILETYPE_ASN1):
686 return crypto.dump_privatekey(format, self.original)
687
688
689 def __getstate__(self):
690 return self.dump()
691
692
693 def __setstate__(self, state):
694 self.__init__(crypto.load_privatekey(crypto.FILETYPE_ASN1, state))
695
696
697 def inspect(self):
698 t = self.original.type()
699 if t == crypto.TYPE_RSA:
700 ts = 'RSA'
701 elif t == crypto.TYPE_DSA:
702 ts = 'DSA'
703 else:
704 ts = '(Unknown Type!)'
705 L = (self.original.bits(), ts, self.keyHash())
706 return '%s-bit %s Key Pair with Hash: %s' % L
707
708
709 def generate(Class, kind=crypto.TYPE_RSA, size=1024):
710 pkey = crypto.PKey()
711 pkey.generate_key(kind, size)
712 return Class(pkey)
713
714
715 def newCertificate(self, newCertData, format=crypto.FILETYPE_ASN1):
716 return PrivateCertificate.load(newCertData, self, format)
717 generate = classmethod(generate)
718
719
720 def requestObject(self, distinguishedName, digestAlgorithm='md5'):
721 req = crypto.X509Req()
722 req.set_pubkey(self.original)
723 distinguishedName._copyInto(req.get_subject())
724 req.sign(self.original, digestAlgorithm)
725 return CertificateRequest(req)
726
727
728 def certificateRequest(self, distinguishedName,
729 format=crypto.FILETYPE_ASN1,
730 digestAlgorithm='md5'):
731 """Create a certificate request signed with this key.
732
733 @return: a string, formatted according to the 'format' argument.
734 """
735 return self.requestObject(distinguishedName, digestAlgorithm).dump(forma t)
736
737
738 def signCertificateRequest(self,
739 issuerDistinguishedName,
740 requestData,
741 verifyDNCallback,
742 serialNumber,
743 requestFormat=crypto.FILETYPE_ASN1,
744 certificateFormat=crypto.FILETYPE_ASN1,
745 secondsToExpiry=60 * 60 * 24 * 365, # One year
746 digestAlgorithm='md5'):
747 """
748 Given a blob of certificate request data and a certificate authority's
749 DistinguishedName, return a blob of signed certificate data.
750
751 If verifyDNCallback returns a Deferred, I will return a Deferred which
752 fires the data when that Deferred has completed.
753 """
754 hlreq = CertificateRequest.load(requestData, requestFormat)
755
756 dn = hlreq.getSubject()
757 vval = verifyDNCallback(dn)
758
759 def verified(value):
760 if not value:
761 raise VerifyError("DN callback %r rejected request DN %r" % (ver ifyDNCallback, dn))
762 return self.signRequestObject(issuerDistinguishedName, hlreq,
763 serialNumber, secondsToExpiry, digestA lgorithm).dump(certificateFormat)
764
765 if isinstance(vval, Deferred):
766 return vval.addCallback(verified)
767 else:
768 return verified(vval)
769
770
771 def signRequestObject(self,
772 issuerDistinguishedName,
773 requestObject,
774 serialNumber,
775 secondsToExpiry=60 * 60 * 24 * 365, # One year
776 digestAlgorithm='md5'):
777 """
778 Sign a CertificateRequest instance, returning a Certificate instance.
779 """
780 req = requestObject.original
781 dn = requestObject.getSubject()
782 cert = crypto.X509()
783 issuerDistinguishedName._copyInto(cert.get_issuer())
784 cert.set_subject(req.get_subject())
785 cert.set_pubkey(req.get_pubkey())
786 cert.gmtime_adj_notBefore(0)
787 cert.gmtime_adj_notAfter(secondsToExpiry)
788 cert.set_serial_number(serialNumber)
789 cert.sign(self.original, digestAlgorithm)
790 return Certificate(cert)
791
792
793 def selfSignedCert(self, serialNumber, **kw):
794 dn = DN(**kw)
795 return PrivateCertificate.fromCertificateAndKeyPair(
796 self.signRequestObject(dn, self.requestObject(dn), serialNumber),
797 self)
798
799
800
801 class OpenSSLCertificateOptions(object):
802 """
803 A factory for SSL context objects for both SSL servers and clients.
804 """
805
806 _context = None
807 # Older versions of PyOpenSSL didn't provide OP_ALL. Fudge it here, just in case.
808 _OP_ALL = getattr(SSL, 'OP_ALL', 0x0000FFFF)
809
810 method = SSL.TLSv1_METHOD
811
812 def __init__(self,
813 privateKey=None,
814 certificate=None,
815 method=None,
816 verify=False,
817 caCerts=None,
818 verifyDepth=9,
819 requireCertificate=True,
820 verifyOnce=True,
821 enableSingleUseKeys=True,
822 enableSessions=True,
823 fixBrokenPeers=False):
824 """
825 Create an OpenSSL context SSL connection context factory.
826
827 @param privateKey: A PKey object holding the private key.
828
829 @param certificate: An X509 object holding the certificate.
830
831 @param method: The SSL protocol to use, one of SSLv23_METHOD,
832 SSLv2_METHOD, SSLv3_METHOD, TLSv1_METHOD. Defaults to TLSv1_METHOD.
833
834 @param verify: If True, verify certificates received from the peer and
835 fail the handshake if verification fails. Otherwise, allow anonymous
836 sessions and sessions with certificates which fail validation. By
837 default this is False.
838
839 @param caCerts: List of certificate authority certificates to
840 send to the client when requesting a certificate. Only used if verify
841 is True, and if verify is True, either this must be specified or
842 caCertsFile must be given. Since verify is False by default,
843 this is None by default.
844
845 @param verifyDepth: Depth in certificate chain down to which to verify.
846 If unspecified, use the underlying default (9).
847
848 @param requireCertificate: If True, do not allow anonymous sessions.
849
850 @param verifyOnce: If True, do not re-verify the certificate
851 on session resumption.
852
853 @param enableSingleUseKeys: If True, generate a new key whenever
854 ephemeral DH parameters are used to prevent small subgroup attacks.
855
856 @param enableSessions: If True, set a session ID on each context. This
857 allows a shortened handshake to be used when a known client reconnects.
858
859 @param fixBrokenPeers: If True, enable various non-spec protocol fixes
860 for broken SSL implementations. This should be entirely safe,
861 according to the OpenSSL documentation, but YMMV. This option is now
862 off by default, because it causes problems with connections between
863 peers using OpenSSL 0.9.8a.
864 """
865
866 assert (privateKey is None) == (certificate is None), "Specify neither o r both of privateKey and certificate"
867 self.privateKey = privateKey
868 self.certificate = certificate
869 if method is not None:
870 self.method = method
871
872 self.verify = verify
873 assert ((verify and caCerts) or
874 (not verify)), "Specify client CA certificate information if and only if enabling certificate verification"
875
876 self.caCerts = caCerts
877 self.verifyDepth = verifyDepth
878 self.requireCertificate = requireCertificate
879 self.verifyOnce = verifyOnce
880 self.enableSingleUseKeys = enableSingleUseKeys
881 self.enableSessions = enableSessions
882 self.fixBrokenPeers = fixBrokenPeers
883
884
885 def __getstate__(self):
886 d = self.__dict__.copy()
887 try:
888 del d['_context']
889 except KeyError:
890 pass
891 return d
892
893
894 def __setstate__(self, state):
895 self.__dict__ = state
896
897
898 def getContext(self):
899 """Return a SSL.Context object.
900 """
901 if self._context is None:
902 self._context = self._makeContext()
903 return self._context
904
905
906 def _makeContext(self):
907 ctx = SSL.Context(self.method)
908 ctx.set_app_data(_SSLApplicationData())
909
910 if self.certificate is not None and self.privateKey is not None:
911 ctx.use_certificate(self.certificate)
912 ctx.use_privatekey(self.privateKey)
913 # Sanity check
914 ctx.check_privatekey()
915
916 verifyFlags = SSL.VERIFY_NONE
917 if self.verify:
918 verifyFlags = SSL.VERIFY_PEER
919 if self.requireCertificate:
920 verifyFlags |= SSL.VERIFY_FAIL_IF_NO_PEER_CERT
921 if self.verifyOnce:
922 verifyFlags |= SSL.VERIFY_CLIENT_ONCE
923 if self.caCerts:
924 store = ctx.get_cert_store()
925 for cert in self.caCerts:
926 store.add_cert(cert)
927
928 def _trackVerificationProblems(conn,cert,errno,depth,preverify_ok):
929 # retcode is the answer OpenSSL's default verifier would have
930 # given, had we allowed it to run.
931 if not preverify_ok:
932 ctx.get_app_data().problems.append(OpenSSLVerifyError(cert, errn o, depth))
933 return preverify_ok
934 ctx.set_verify(verifyFlags, _trackVerificationProblems)
935
936 if self.verifyDepth is not None:
937 ctx.set_verify_depth(self.verifyDepth)
938
939 if self.enableSingleUseKeys:
940 ctx.set_options(SSL.OP_SINGLE_DH_USE)
941
942 if self.fixBrokenPeers:
943 ctx.set_options(self._OP_ALL)
944
945 if self.enableSessions:
946 sessionName = hashlib.md5("%s-%d" % (reflect.qual(self.__class__), _ sessionCounter())).hexdigest()
947 ctx.set_session_id(sessionName)
948
949 return ctx
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/internet/_posixstdio.py ('k') | third_party/twisted_8_1/twisted/internet/_threadedselect.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698