Add cert validation support & internal clean-up, see Changelog

Prepare for 0.14 release


git-svn-id: svn://10.0.0.236/trunk@264395 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jdennis%redhat.com
2012-11-01 17:41:48 +00:00
parent 973734690f
commit b0fc292f32
15 changed files with 2984 additions and 500 deletions

View File

@@ -9,6 +9,7 @@ doc/examples/cert_dump.py
doc/examples/httplib_example.py
doc/examples/ssl_example.py
doc/examples/verify_server.py
doc/examples/verify_cert.py
test/run_tests
test/setup_certs.py
test/test_cert_components.py

View File

@@ -1,3 +1,130 @@
2012-10-24 John Dennis <jdennis@redhat.com> 0.14
External Changes:
-----------------
The primary enhancement in this version is support of certifcate
validation, especially CA certs which can be done via
Certificate.verify() or Certificate.is_ca_cert(). When cert
validation fails you can now obtain diagnostic information as to why
the cert failed to validate. This is encapsulated in the
CertVerifyLog class which is a iterable collection of
CertVerifyLogNode objects. Most people will probablby just print the
string representation of the returned CertVerifyLog object. Cert
validation logging is handled by the Certificate.verify() method.
Support has also been added for the various key usage and cert type
entities which feature prominently during cert validation.
* The following classes were added:
- nss.CertVerifyLogNode
- nss.CertVerifyLog
- error.CertVerifyError (exception)
* The following class methods were added:
- nss.Certificate.is_ca_cert
- nss.Certificate.verify
- nss.Certificate.verify_with_log
- nss.Certificate.get_cert_chain
- nss.PK11Slot.list_certs
- nss.CertVerifyLogNode.format_lines
- nss.CertVerifyLog.format_lines
* The following class properties were added:
- nss.CertVerifyLogNode.certificate
- nss.CertVerifyLogNode.error
- nss.CertVerifyLogNode.depth
- nss.CertVerifyLog.count
* The following module functions were added:
- nss.x509_cert_type
- nss.key_usage_flags
- nss.list_certs
- nss.find_certs_from_email_addr
- nss.find_certs_from_nickname
- nss.get_use_pkix_for_validation
- nss.set_use_pkix_for_validation
* The following files were added:
doc/examples/verify_cert.py
* The following constants were added:
- nss.KU_DIGITAL_SIGNATURE
- nss.KU_NON_REPUDIATION
- nss.KU_KEY_ENCIPHERMENT
- nss.KU_DATA_ENCIPHERMENT
- nss.KU_KEY_AGREEMENT
- nss.KU_KEY_CERT_SIGN
- nss.KU_CRL_SIGN
- nss.KU_ENCIPHER_ONLY
- nss.KU_ALL
- nss.KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION
- nss.KU_KEY_AGREEMENT_OR_ENCIPHERMENT
- nss.KU_NS_GOVT_APPROVED
- nss.PK11CertListUnique
- nss.PK11CertListUser
- nss.PK11CertListRootUnique
- nss.PK11CertListCA
- nss.PK11CertListCAUnique
- nss.PK11CertListUserUnique
- nss.PK11CertListAll
- nss.certUsageSSLClient
- nss.certUsageSSLServer
- nss.certUsageSSLServerWithStepUp
- nss.certUsageSSLCA
- nss.certUsageEmailSigner
- nss.certUsageEmailRecipient
- nss.certUsageObjectSigner
- nss.certUsageUserCertImport
- nss.certUsageVerifyCA
- nss.certUsageProtectedObjectSigner
- nss.certUsageStatusResponder
- nss.certUsageAnyCA
* cert_dump.py extended to print NS_CERT_TYPE_EXTENSION
* cert_usage_flags, nss_init_flags now support optional repr_kind parameter
* error codes and descriptions were updated from upstream NSPR & NSS.
Internal Changes:
-----------------
* Reimplement exception handling
- NSPRError is now derived from StandardException instead of
EnvironmentError. It was never correct to derive from
EnvironmentError but was difficult to implement a new subclassed
exception with it's own attributes, using EnvironmentError had
been expedient.
- NSPRError now derived from StandardException, provides:
* errno (numeric error code)
* strerror (error description associated with error code)
* error_message (optional detailed message)
* error_code (alias for errno)
* error_desc (alias for strerror)
- CertVerifyError derived from NSPRError, extends with:
* usages (bitmask of returned usages)
* log (CertVerifyLog object)
* Expose error lookup to sibling modules
* Use macros for bitmask_to_list functions to reduce code
duplication and centralize logic.
* Add repr_kind parameter to cert_trust_flags_str()
* Add support for repr_kind AsEnumName to bitstring table lookup.
* Add cert_type_bitstr_to_tuple() lookup function
* Add PRTimeConvert(), used to convert Python time values
to PRTime, centralizes conversion logic, reduces duplication
* Add Certificate_summary_format_lines() utility to generate
concise certificate identification info for output.
2012-10-05 John Dennis <jdennis@redhat.com> 0.13
* Fix NSS SECITEM_CompareItem bug via workaround.

View File

@@ -38,6 +38,10 @@ def print_extension(level, extension):
print nss.indented_format([(level, 'Usages:')])
print nss.indented_format(nss.make_line_fmt_tuples(level+1, nss.x509_key_usage(extension.value)))
elif oid_tag == nss.SEC_OID_NS_CERT_EXT_CERT_TYPE:
print nss.indented_format([(level, 'Types:')])
print nss.indented_format(nss.make_line_fmt_tuples(level+1, nss.x509_cert_type(extension.value)))
elif oid_tag == nss.SEC_OID_X509_SUBJECT_KEY_ID:
print nss.indented_format([(level, 'Data:')])
print nss.indented_format(nss.make_line_fmt_tuples(level+1,

View File

@@ -0,0 +1,278 @@
#!/usr/bin/python
import sys
import optparse
import nss.nss as nss
import nss.error as nss_error
'''
This example illustrates how one can use NSS to verify (validate) a
certificate. Certificate validation starts with an intended usage for
the certificate and returns a set of flags for which the certificate
is actually valid for. When a cert fails validation it can be
useful to obtain diagnostic information as to why. One of the
verification methods includes returning the diagnostic information in
what is called a log. A cert can also be checked to see if it
qualifies as a CA cert.
The actual code to verify the cert is simple and straight forward. The
complexity in this example derives mainly from handling all the
options necessary to make the example flexible.
* The certificate may either be read from a file or loaded by nickname
from a NSS database.
* You can optionally print the details the cert.
* You can specify a set of intened cert usages (each -u option adds an
other usage to the set).
* You can enable/disable checking the cert signature.
* You can enable/disable using the log variant.
* You can enable/disable verifying the cert's CA status.
* The results are pretty printed.
'''
#-------------------------------------------------------------------------------
cert_usage_map = {
'CheckAllUsages' : nss.certificateUsageCheckAllUsages,
'SSLClient' : nss.certificateUsageSSLClient,
'SSLServer' : nss.certificateUsageSSLServer,
'SSLServerWithStepUp' : nss.certificateUsageSSLServerWithStepUp,
'SSLCA' : nss.certificateUsageSSLCA,
'EmailSigner' : nss.certificateUsageEmailSigner,
'EmailRecipient' : nss.certificateUsageEmailRecipient,
'ObjectSigner' : nss.certificateUsageObjectSigner,
'UserCertImport' : nss.certificateUsageUserCertImport,
'VerifyCA' : nss.certificateUsageVerifyCA,
'ProtectedObjectSigner' : nss.certificateUsageProtectedObjectSigner,
'StatusResponder' : nss.certificateUsageStatusResponder,
'AnyCA' : nss.certificateUsageAnyCA,
}
#-------------------------------------------------------------------------------
def password_callback(slot, retry, password):
return options.db_passwd
def indented_output(msg, l, level=0):
msg = '%s:' % msg
lines = []
if not l:
l = ['--']
lines.extend(nss.make_line_fmt_tuples(level, msg))
lines.extend(nss.make_line_fmt_tuples(level+1, l))
return nss.indented_format(lines)
def indented_obj(msg, obj, level=0):
msg = '%s:' % msg
lines = []
lines.extend(nss.make_line_fmt_tuples(level, msg))
lines.extend(obj.format_lines(level+1))
return nss.indented_format(lines)
#-------------------------------------------------------------------------------
def main():
# Command line argument processing
parser = optparse.OptionParser()
parser.set_defaults(dbdir = '/etc/pki/nssdb',
db_passwd = 'db_passwd',
input_format = 'pem',
check_sig = True,
print_cert = False,
with_log = True,
check_ca = True,
)
param_group = optparse.OptionGroup(parser, 'NSS Database',
'Specify & control the NSS Database')
param_group.add_option('-d', '--dbdir', dest='dbdir',
help='NSS database directory, default="%default"')
param_group.add_option('-P', '--db-passwd', dest='db_passwd',
help='NSS database password, default="%default"')
param_group = optparse.OptionGroup(parser, 'Certificate',
'Specify how the certificate is loaded')
param_group.add_option('-f', '--file', dest='cert_filename',
help='read cert from file')
param_group.add_option('--format', dest='input_format', choices=['pem', 'der'],
help='import format for certificate (der|pem) default="%default"')
param_group.add_option('-n', '--nickname', dest='cert_nickname',
help='load cert from NSS database by looking it up under this nickname')
param_group = optparse.OptionGroup(parser, 'Validation',
'Control the validation')
param_group.add_option('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
help='may be specified multiple times, default="CheckAllUsages", may be one of: %s' % ', '.join(sorted(cert_usage_map.keys())))
param_group.add_option('-c', '--check-sig', action='store_true', dest='check_sig',
help='check signature default=%default')
param_group.add_option('-C', '--no-check-sig', action='store_false', dest='check_sig',
help='check signature')
param_group.add_option('-l', '--log', action='store_true', dest='with_log',
help='use verify log, default=%default')
param_group.add_option('-L', '--no-log', action='store_false', dest='with_log',
help='use verify log, default=%default')
param_group.add_option('-a', '--check-ca', action='store_true', dest='check_ca',
help='check if cert is CA, default=%default')
param_group.add_option('-A', '--no-check-ca', action='store_false', dest='check_ca',
help='check if cert is CA, default=%default')
param_group = optparse.OptionGroup(parser, 'Miscellaneous',
'Miscellaneous options')
param_group.add_option('-p', '--print-cert', action='store_true', dest='print_cert',
help='print the certificate in a friendly fashion, default=%default')
options, args = parser.parse_args()
# Process the command line arguments
# Get usage bitmask
if options.cert_usage:
intended_usage = 0
for usage in options.cert_usage:
try:
flag = cert_usage_map[usage]
except KeyError:
print "Unknown usage '%s', valid values: %s" % (usage, ', '.join(sorted(cert_usage_map.keys())))
return 1
else:
intended_usage |= flag
else:
# We can't use nss.certificateUsageCheckAllUsages here because
# it's a special value of zero instead of being the bitwise OR
# of all the certificateUsage* flags (go figure!)
intended_usage = 0
for usage in cert_usage_map.values():
intended_usage |= usage
if options.cert_filename and options.cert_nickname:
print >>sys.stderr, "You may not specify both a cert filename and a nickname, only one or the other"
return 1
if not options.cert_filename and not options.cert_nickname:
print >>sys.stderr, "You must specify either a cert filename or a nickname to load"
return 1
# Initialize NSS.
print indented_output('NSS Database', options.dbdir)
print
nss.nss_init(options.dbdir)
certdb = nss.get_default_certdb()
nss.set_password_callback(password_callback)
# Load the cert
if options.cert_filename:
# Read the certificate as DER encoded data then initialize a Certificate from the DER data
filename = options.cert_filename
si = nss.read_der_from_file(filename, options.input_format.lower() == 'pem')
# Parse the DER encoded data returning a Certificate object
cert = nss.Certificate(si)
else:
try:
cert = nss.find_cert_from_nickname(options.cert_nickname)
except Exception, e:
print e
print >>sys.stderr, 'Unable to load cert nickname "%s" from database "%s"' % \
(options.cert_nickname, options.dbdir)
return 1
# Dump the cert if the user wants to see it
if options.print_cert:
print cert
else:
print indented_output('cert subject', cert.subject)
print
# Dump the usages attached to the cert
print indented_output('cert has these usages', nss.cert_type_flags(cert.cert_type))
# Should we check if the cert is a CA cert?
if options.check_ca:
# CA Cert?
is_ca, cert_type = cert.is_ca_cert(True)
print
print indented_output('is CA cert boolean', is_ca)
print indented_output('is CA cert returned usages', nss.cert_type_flags(cert_type))
print
print indented_output('verifying usages for', nss.cert_usage_flags(intended_usage))
print
# Use the log or non-log variant to verify the cert
#
# Note: Anytime a NSPR or NSS function returns an error in python-nss it
# raises a NSPRError exception. When an exception is raised the normal
# return values are discarded because the flow of control continues at
# the first except block prepared to catch the exception. Normally this
# is what is desired because the return values would be invalid due to
# the error. However the certificate verification functions are an
# exception (no pun intended). An error might be returned indicating the
# cert failed verification but you may still need access to the returned
# usage bitmask and the log (if using the log variant). To handle this a
# special error exception `CertVerifyError` (derived from `NSPRError`)
# is defined which in addition to the normal NSPRError fields will also
# contain the returned usages and optionally the CertVerifyLog
# object. If no exception is raised these are returned as normal return
# values.
approved_usage = 0
if options.with_log:
try:
approved_usage, log = cert.verify_with_log(certdb, options.check_sig, intended_usage, None)
except nss_error.CertVerifyError, e:
# approved_usage and log available in CertVerifyError exception on failure.
print e
print
print indented_obj('log', e.log)
print
print indented_output('approved usages from exception', nss.cert_usage_flags(e.usages))
approved_usage = e.usages # Get the returned usage bitmask from the exception
except Exception, e:
print e
else:
print indented_output('approved usages', nss.cert_usage_flags(approved_usage))
if log.count:
print
print indented_obj('log', log)
else:
try:
approved_usage = cert.verify(certdb, options.check_sig, intended_usage, None)
except nss_error.CertVerifyError, e:
# approved_usage available in CertVerifyError exception on failure.
print e
print indented_output('approved usages from exception', nss.cert_usage_flags(e.usages))
approved_usage = e.usages # Get the returned usage bitmask from the exception
except Exception, e:
print e
else:
print indented_output('approved usages', nss.cert_usage_flags(approved_usage))
# The cert is valid if all the intended usages are in the approved usages
valid = (intended_usage & approved_usage) == intended_usage
print
if valid:
print indented_output('SUCCESS: cert is approved for', nss.cert_usage_flags(intended_usage))
return 0
else:
print indented_output('FAIL: cert not approved for', nss.cert_usage_flags(intended_usage ^ approved_usage))
return 1
#-------------------------------------------------------------------------------
if __name__ == "__main__":
sys.exit(main())

View File

@@ -17,7 +17,7 @@ from distutils.util import subst_vars, change_root
from distutils.command.build_py import build_py as _build_py
from distutils.command.sdist import sdist as _sdist
version = "0.13"
version = "0.14.0alpha"
doc_manifest = [
[['include README LICENSE* doc/ChangeLog',
@@ -369,7 +369,7 @@ def main(argv):
author_email = 'jdennis@redhat.com',
maintainer = 'John Dennis',
maintainer_email = 'jdennis@redhat.com',
license = 'MPLv1.1 or GPLv2+ or LGPLv2+',
license = 'MPLv2.0 or GPLv2+ or LGPLv2+',
platforms = 'posix',
url = 'http://www.mozilla.org/projects/security/pki/python-nss',
download_url = '',

View File

@@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* General NSPR 2.0 errors */
/* Caller must #include "prerror.h" */

View File

@@ -483,7 +483,75 @@ ER3(SEC_ERROR_TOKEN_NOT_LOGGED_IN, (SEC_ERROR_BASE + 155),
"The operation failed because the PKCS#11 token is not logged in.")
ER3(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, (SEC_ERROR_BASE + 156),
"OCSP Trusted Responder Cert is invalid.")
"Configured OCSP responder's certificate is invalid.")
ER3(SEC_ERROR_OCSP_BAD_SIGNATURE, (SEC_ERROR_BASE + 157),
"OCSP response has an invalid signature.")
ER3(SEC_ERROR_OUT_OF_SEARCH_LIMITS, (SEC_ERROR_BASE + 158),
"Cert validation search is out of search limits")
ER3(SEC_ERROR_INVALID_POLICY_MAPPING, (SEC_ERROR_BASE + 159),
"Policy mapping contains anypolicy")
ER3(SEC_ERROR_POLICY_VALIDATION_FAILED, (SEC_ERROR_BASE + 160),
"Cert chain fails policy validation")
ER3(SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, (SEC_ERROR_BASE + 161),
"Unknown location type in cert AIA extension")
ER3(SEC_ERROR_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 162),
"Server returned bad HTTP response")
ER3(SEC_ERROR_BAD_LDAP_RESPONSE, (SEC_ERROR_BASE + 163),
"Server returned bad LDAP response")
ER3(SEC_ERROR_FAILED_TO_ENCODE_DATA, (SEC_ERROR_BASE + 164),
"Failed to encode data with ASN1 encoder")
ER3(SEC_ERROR_BAD_INFO_ACCESS_LOCATION, (SEC_ERROR_BASE + 165),
"Bad information access location in cert extension")
ER3(SEC_ERROR_LIBPKIX_INTERNAL, (SEC_ERROR_BASE + 166),
"Libpkix internal error occurred during cert validation.")
ER3(SEC_ERROR_PKCS11_GENERAL_ERROR, (SEC_ERROR_BASE + 167),
"A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred.")
ER3(SEC_ERROR_PKCS11_FUNCTION_FAILED, (SEC_ERROR_BASE + 168),
"A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed.")
ER3(SEC_ERROR_PKCS11_DEVICE_ERROR, (SEC_ERROR_BASE + 169),
"A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.")
ER3(SEC_ERROR_BAD_INFO_ACCESS_METHOD, (SEC_ERROR_BASE + 170),
"Unknown information access method in certificate extension.")
ER3(SEC_ERROR_CRL_IMPORT_FAILED, (SEC_ERROR_BASE + 171),
"Error attempting to import a CRL.")
ER3(SEC_ERROR_EXPIRED_PASSWORD, (SEC_ERROR_BASE + 172),
"The password expired.")
ER3(SEC_ERROR_LOCKED_PASSWORD, (SEC_ERROR_BASE + 173),
"The password is locked.")
ER3(SEC_ERROR_UNKNOWN_PKCS11_ERROR, (SEC_ERROR_BASE + 174),
"Unknown PKCS #11 error.")
ER3(SEC_ERROR_BAD_CRL_DP_URL, (SEC_ERROR_BASE + 175),
"Invalid or unsupported URL in CRL distribution point name.")
ER3(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, (SEC_ERROR_BASE + 176),
"The certificate was signed using a signature algorithm that is disabled because it is not secure.")
#ifdef SEC_ERROR_LEGACY_DATABASE
ER3(SEC_ERROR_LEGACY_DATABASE, (SEC_ERROR_BASE + 177),
"The certificate/key database is in an old, unsupported format.")
#endif
#ifdef SEC_ERROR_APPLICATION_CALLBACK_ERROR
ER3(SEC_ERROR_APPLICATION_CALLBACK_ERROR, (SEC_ERROR_BASE + 178),
"The certificate was rejected by extra checks in the application.")
#endif

View File

@@ -20,7 +20,8 @@ ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
"Unable to communicate securely with peer: peers's certificate was rejected.")
/* unused (SSL_ERROR_BASE + 5),*/
ER3(SSL_ERROR_UNUSED_5, SSL_ERROR_BASE + 5,
"Unrecognized SSL error code.")
ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
"The server has encountered bad data from the client.")
@@ -34,7 +35,8 @@ ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
"Peer using unsupported version of security protocol.")
/* unused (SSL_ERROR_BASE + 10),*/
ER3(SSL_ERROR_UNUSED_10, SSL_ERROR_BASE + 10,
"Unrecognized SSL error code.")
ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
"Client authentication failed: private key in key database does not match public key in certificate database.")
@@ -42,9 +44,8 @@ ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
defined in sslerr.h
*/
ER3(SSL_ERROR_POST_WARNING, SSL_ERROR_BASE + 13,
"Unrecognized SSL error code.")
ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
"Peer only supports SSL version 2, which is locally disabled.")
@@ -71,7 +72,6 @@ ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
"Cannot connect: SSL peer is in another FORTEZZA domain.")
ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
"An unknown SSL cipher suite has been requested.")
@@ -285,7 +285,7 @@ ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
"Cannot communicate securely with peer: no common compression algorithm(s).")
ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
"Cannot initiate another SSL handshake until current handshake is complete.")
"Cannot perform the operation until the handshake is complete.")
ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
"Received incorrect handshakes hash values from peer.")
@@ -352,3 +352,61 @@ ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT , (SSL_ERROR_BASE + 107),
ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT , (SSL_ERROR_BASE + 108),
"SSL peer reported bad certificate hash value.")
ER3(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 109),
"SSL received an unexpected New Session Ticket handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 110),
"SSL received a malformed New Session Ticket handshake message.")
ER3(SSL_ERROR_DECOMPRESSION_FAILURE, (SSL_ERROR_BASE + 111),
"SSL received a compressed record that could not be decompressed.")
ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, (SSL_ERROR_BASE + 112),
"Renegotiation is not allowed on this SSL socket.")
ER3(SSL_ERROR_UNSAFE_NEGOTIATION, (SSL_ERROR_BASE + 113),
"Peer attempted old style (potentially vulnerable) handshake.")
ER3(SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD, (SSL_ERROR_BASE + 114),
"SSL received an unexpected uncompressed record.")
ER3(SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY, (SSL_ERROR_BASE + 115),
"SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.")
ER3(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, (SSL_ERROR_BASE + 116),
"SSL received invalid NPN extension data.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2, (SSL_ERROR_BASE + 117),
"SSL feature not supported for SSL 2.0 connections.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS, (SSL_ERROR_BASE + 118),
"SSL feature not supported for servers.")
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_CLIENTS, (SSL_ERROR_BASE + 119),
"SSL feature not supported for clients.")
#ifdef SSL_ERROR_INVALID_VERSION_RANGE
ER3(SSL_ERROR_INVALID_VERSION_RANGE, (SSL_ERROR_BASE + 120),
"SSL version range is not valid.")
#endif
#ifdef SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION
ER3(SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION, (SSL_ERROR_BASE + 121),
"SSL peer selected a cipher suite disallowed for the selected protocol version.")
#endif
#ifdef SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST
ER3(SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 122),
"SSL received a malformed Hello Verify Request handshake message.")
#endif
#ifdef SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 123),
"SSL received an unexpected Hello Verify Request handshake message.")
#endif
#ifdef SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION
ER3(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, (SSL_ERROR_BASE + 124),
"SSL feature not supported for the protocol version.")
#endif

View File

@@ -312,5 +312,5 @@ FAQ
To be added
"""
__version__ = '0.13'
__version__ = '0.14.0alpha'

View File

@@ -68,6 +68,8 @@ typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t);
#define PyNone_Check(x) ((x) == Py_None)
#define CALL_BASE(type, func, ...) (type)->tp_base->tp_##func(__VA_ARGS__)
#define TYPE_READY(type) \
{ \
if (PyType_Ready(&type) < 0) \

View File

@@ -8,15 +8,7 @@
#define NSS_ERROR_MODULE
#include "py_nspr_error.h"
static PyObject *NSPR_Exception = NULL;
typedef struct {
PRErrorCode num;
const char *name;
const char *string;
} NSPRErrorDesc;
#include "py_nspr_common.h"
#include "nspr.h"
#include "seccomon.h"
@@ -27,7 +19,26 @@ typedef struct {
#include "secerr.h"
#include "sslerr.h"
typedef struct {
PyBaseExceptionObject base;
PyObject *error_desc;
PyObject *error_message;
PyObject *str_value;
int error_code;
} NSPRError;
typedef struct {
NSPRError base;
PyObject *log;
unsigned int usages;
} CertVerifyError;
static PyObject *empty_tuple = NULL;
static PyTypeObject NSPRErrorType;
static PyTypeObject CertVerifyErrorType;
NSPRErrorDesc nspr_errors[] = {
{0, "SUCCESS", "Success"},
#include "SSLerrs.h"
#include "SECerrs.h"
#include "NSPRerrs.h"
@@ -46,6 +57,23 @@ cmp_error(const void *p1, const void *p2)
const int nspr_error_count = sizeof(nspr_errors) / sizeof(NSPRErrorDesc);
static int
IntOrNoneConvert(PyObject *obj, int *param)
{
if (PyInt_Check(obj)) {
*param = PyInt_AsLong(obj);
return 1;
}
if (PyNone_Check(obj)) {
return 1;
}
PyErr_Format(PyExc_TypeError, "must be int or None, not %.50s",
Py_TYPE(obj)->tp_name);
return 0;
}
static PRStatus
init_nspr_errors(void) {
int low = 0;
@@ -102,36 +130,31 @@ lookup_nspr_error(PRErrorCode num) {
}
static PyObject *
set_nspr_error(const char *format, ...)
get_error_desc(PRErrorCode *p_error_code)
{
va_list vargs;
PyObject *v;
const NSPRErrorDesc *error_desc;
char *pr_err_msg=NULL;
PRErrorCode error_code = 0;
NSPRErrorDesc const *error_desc = NULL;
char *pr_err_msg = NULL;
PRInt32 pr_err_msg_len;
PRErrorCode error_code;
PyObject *detail = NULL;
char *final_err_msg=NULL;
char *final_err_msg = NULL;
PyObject *result = NULL;
if (format) {
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, format);
#else
va_start(vargs);
#endif
detail = PyString_FromFormatV(format, vargs);
va_end(vargs);
}
error_code = PR_GetError();
error_desc = lookup_nspr_error(error_code);
if ((pr_err_msg_len = PR_GetErrorTextLength())) {
if ((pr_err_msg = PyMem_Malloc(pr_err_msg_len + 1))) {
PR_GetErrorText(pr_err_msg);
if (!p_error_code || *p_error_code == -1) {
error_code = PR_GetError();
if (p_error_code) {
*p_error_code = error_code;
}
if ((pr_err_msg_len = PR_GetErrorTextLength())) {
if ((pr_err_msg = PyMem_Malloc(pr_err_msg_len + 1))) {
PR_GetErrorText(pr_err_msg);
}
}
} else {
error_code = *p_error_code;
}
error_desc = lookup_nspr_error(error_code);
if (pr_err_msg && error_desc) {
final_err_msg = PR_smprintf("%s (%s) %s", pr_err_msg, error_desc->name, error_desc->string);
} else if (error_desc) {
@@ -142,23 +165,97 @@ set_nspr_error(const char *format, ...)
final_err_msg = PR_smprintf("error (%d) unknown", error_code);
}
if (detail) {
v = Py_BuildValue("(isS)", error_code, final_err_msg, detail);
Py_DECREF(detail);
} else {
v = Py_BuildValue("(is)", error_code, final_err_msg);
}
if (v != NULL) {
PyErr_SetObject(NSPR_Exception, v);
Py_DECREF(v);
}
result = PyString_FromString(final_err_msg);
if (final_err_msg) PR_smprintf_free(final_err_msg);
if (pr_err_msg) PyMem_Free(pr_err_msg);
return result;
}
static PyObject *
set_nspr_error(const char *format, ...)
{
va_list vargs;
PyObject *error_message = NULL;
PyObject *kwds = NULL;
PyObject *exception_obj = NULL;
if (format) {
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, format);
#else
va_start(vargs);
#endif
error_message = PyString_FromFormatV(format, vargs);
va_end(vargs);
}
if ((kwds = PyDict_New()) == NULL) {
return NULL;
}
if (error_message) {
if (PyDict_SetItemString(kwds, "error_message", error_message) != 0) {
return NULL;
}
}
exception_obj = PyObject_Call((PyObject *)&NSPRErrorType, empty_tuple, kwds);
Py_DECREF(kwds);
PyErr_SetObject((PyObject *)&NSPRErrorType, exception_obj);
return NULL;
}
static PyObject *
set_cert_verify_error(unsigned int usages, PyObject *log, const char *format, ...)
{
va_list vargs;
PyObject *error_message = NULL;
PyObject *kwds = NULL;
PyObject *exception_obj = NULL;
if (format) {
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, format);
#else
va_start(vargs);
#endif
error_message = PyString_FromFormatV(format, vargs);
va_end(vargs);
}
if ((kwds = PyDict_New()) == NULL) {
return NULL;
}
if (error_message) {
if (PyDict_SetItemString(kwds, "error_message", error_message) != 0) {
return NULL;
}
}
if (PyDict_SetItemString(kwds, "usages", PyInt_FromLong(usages)) != 0) {
return NULL;
}
if (log) {
if (PyDict_SetItemString(kwds, "log", log) != 0) {
return NULL;
}
}
exception_obj = PyObject_Call((PyObject *)&CertVerifyErrorType, empty_tuple, kwds);
Py_DECREF(kwds);
PyErr_SetObject((PyObject *)&CertVerifyErrorType, exception_obj);
return NULL;
}
PyDoc_STRVAR(io_get_nspr_error_string_doc,
"get_nspr_error_string(number) -> string\n\
\n\
@@ -291,13 +388,422 @@ static PyObject *tuple_str(PyObject *tuple)
return text;
}
/* ========================================================================== */
/* ========================= NSPRError Class ========================== */
/* ========================================================================== */
/* ============================ Attribute Access ============================ */
static PyMemberDef NSPRError_members[] = {
{"errno", T_INT, offsetof(NSPRError, error_code), READONLY,
PyDoc_STR("NSS error code")},
{"error_code", T_INT, offsetof(NSPRError, error_code), READONLY,
PyDoc_STR("NSS error code")},
{"strerror", T_OBJECT, offsetof(NSPRError, error_desc), READONLY,
PyDoc_STR("NSS error code description")},
{"error_desc", T_OBJECT, offsetof(NSPRError, error_desc), READONLY,
PyDoc_STR("NSS error code description")},
{"error_message", T_OBJECT, offsetof(NSPRError, error_message), READONLY,
PyDoc_STR("error message specific to this error")},
{NULL} /* Sentinel */
};
/* ============================== Class Methods ============================= */
static PyObject *
NSPRError_str(NSPRError *self)
{
TraceMethodEnter(self);
Py_XINCREF(self->str_value);
return self->str_value;
}
/* =========================== Class Construction =========================== */
static int
NSPRError_traverse(NSPRError *self, visitproc visit, void *arg)
{
Py_VISIT(self->error_desc);
Py_VISIT(self->error_message);
Py_VISIT(self->str_value);
CALL_BASE(&NSPRErrorType, traverse, (PyObject *)self, visit, arg);
return 0;
}
static int
NSPRError_clear(NSPRError* self)
{
TraceMethodEnter(self);
Py_CLEAR(self->error_desc);
Py_CLEAR(self->error_message);
Py_CLEAR(self->str_value);
CALL_BASE(&NSPRErrorType, clear, (PyObject *)self);
return 0;
}
static void
NSPRError_dealloc(NSPRError* self)
{
TraceMethodEnter(self);
NSPRError_clear(self);
Py_TYPE(self)->tp_free((PyObject *)self);
}
PyDoc_STRVAR(NSPRError_doc,
"NSPRError(error_message=None, error_code=None)\n\
\n\
:Parameters:\n\
error_message : string\n\
Detail message specific to this error.\n\
error_code : int\n\
NSS or NSPR error value, if None get current error\n\
\n\
Exception object (derived from StandardException), raised when an\n\
NSS or NSPR error occurs. The error model in python-nss is anytime\n\
a NSS or NSPR C function returns an error the python-nss binding\n\n\
raises a NSPRError exception.\n\
\n\
Raised internally, there should be no need to raise this exception\n\
from with a Python program using python-nss.\n\
\n\
The error_message is an optional string detailing the specifics\n\
of an error.\n\
\n\
If the error_code is not passed then the current error is queried.\n\
\n\
A NSPRError contains the following attributes:\n\
\n\
error_code\n\
The numeric NSPR or NSS error code (integer).\n\
If not passed the current NSPR or NSS error for the\n\
current thread is queried and substituted.\n\
error_desc\n\
Error description associated with error code (string).\n\
error_message\n\
Optional message with details specific to the error (string).\n\
errno\n\
Alias for errno.\n\
strerr\n\
Alias for error_desc.\n\
\n\
");
static int
NSPRError_init(NSPRError *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"error_message", "error_code", NULL};
const char *error_message = NULL;
int error_code = -1;
PyObject *error_desc = NULL;
PyObject *str_value = NULL;
TraceMethodEnter(self);
CALL_BASE(&NSPRErrorType, init, (PyObject *)self, args, NULL);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zO&:NSPRError", kwlist,
&error_message,
IntOrNoneConvert, &error_code))
return -1;
error_desc = get_error_desc(&error_code);
if (error_message) {
str_value = PyString_FromFormat("%s: %s",
error_message,
error_desc ? PyString_AsString(error_desc) :
_("Error description unavailable"));
} else {
str_value = error_desc;
}
Py_CLEAR(self->base.message);
self->base.message = str_value;
Py_XINCREF(self->base.message);
Py_CLEAR(self->str_value);
self->str_value = str_value;
Py_XINCREF(self->str_value);
Py_CLEAR(self->error_desc);
self->error_desc = error_desc;
Py_XINCREF(self->error_desc);
self->error_code = error_code;
return 0;
}
static PyTypeObject NSPRErrorType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"nss.error.NSPRError", /* tp_name */
sizeof(NSPRError), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)NSPRError_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(reprfunc)NSPRError_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
NSPRError_doc, /* tp_doc */
(traverseproc)NSPRError_traverse, /* tp_traverse */
(inquiry)NSPRError_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
NSPRError_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)NSPRError_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
/* ========================================================================== */
/* ========================= CertVerifyError Class ========================== */
/* ========================================================================== */
/* ============================ Attribute Access ============================ */
static PyMemberDef CertVerifyError_members[] = {
{"usages", T_UINT, offsetof(CertVerifyError, usages), READONLY,
PyDoc_STR("usages returned by NSS")},
{"log", T_OBJECT, offsetof(CertVerifyError, log), READONLY,
PyDoc_STR("verifcation log, see `CertVerifyLog`")},
{NULL} /* Sentinel */
};
/* ============================== Class Methods ============================= */
static PyObject *
CertVerifyError_str(CertVerifyError *self)
{
PyObject *super_str = NULL;
PyObject *str = NULL;
TraceMethodEnter(self);
if ((super_str = CALL_BASE(&CertVerifyErrorType, str, (PyObject *)self)) == NULL) {
return NULL;
}
str = PyString_FromFormat("%s usages=%#x", PyString_AsString(super_str), self->usages);
Py_DECREF(super_str);
return str;
}
/* =========================== Class Construction =========================== */
static int
CertVerifyError_traverse(CertVerifyError *self, visitproc visit, void *arg)
{
Py_VISIT(self->log);
CALL_BASE(&CertVerifyErrorType, traverse, (PyObject *)self, visit, arg);
return 0;
}
static int
CertVerifyError_clear(CertVerifyError* self)
{
TraceMethodEnter(self);
Py_CLEAR(self->log);
CALL_BASE(&CertVerifyErrorType, clear, (PyObject *)self);
return 0;
}
static void
CertVerifyError_dealloc(CertVerifyError* self)
{
TraceMethodEnter(self);
CertVerifyError_clear(self);
Py_TYPE(self)->tp_free((PyObject *)self);
}
PyDoc_STRVAR(CertVerifyError_doc,
"CertVerifyError(error_message=None, error_code=None, usages=None, log=None)\n\
\n\
:Parameters:\n\
error_message : string\n\
Detail message specific to this error.\n\
error_code : int\n\
NSS or NSPR error value, if None get current error\n\
usages : int\n\
The returned usages bitmaks from the verify function.\n\
log : `CertVerifyLog` object\n\
The verification log generated during the verification\n\
operation.\n\
\n\
Exception object (derived from NSPRError), raised when an\n\
error occurs during certificate verification.\n\
\n\
Raised internally, there should be no need to raise this exception\n\
from with a Python program using python-nss.\n\
\n\
Certificate verification presents a problem for the normal error\n\
handling model whereby any error returned from an underlying C\n\
function causes a `NSPRError` exception to be raised. When an\n\
exception is raised the return values are lost. It is unusual for a\n\
function to have useful return values when the function also returns\n\
an error.\n\
\n\
The certificate verification functions are one such example. If\n\
verification fails useful information concerning validated usages and\n\
the verification log need to be available. But to be consistent with\n\
model of always raising an exception on an error return some other\n\
mechanism is needed to return the extra information. The solution is\n\
to embed the information which normally would have been in the return\n\
values in the exception object where it can be queried. The\n\
CertVerifyError contails the returned usages bitmask and optionally\n\
the `CertVerifyLog` verification log object if requested.\n\
\n\
In addtion to the attributes in a `NSPRError` a CertVerifyError contains\n\
the following attributes:\n\
\n\
usages\n\
The retured usages bitmask (unsigned int) from the Certificate\n\
verification function.\n\
log\n\
The (optional) `CertVerifyLog` object which contains the\n\
diagnostic information for why a certificate failed to validate.\n\
\n\
");
static int
CertVerifyError_init(CertVerifyError *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"error_message", "error_code", "usages", "log", NULL};
const char *error_message = NULL;
int error_code = -1;
unsigned int usages = 0;
PyObject *log = NULL;
PyObject *super_kwds = NULL;
int result = 0;
TraceMethodEnter(self);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zO&IO:CertVerifyError", kwlist,
&error_message,
IntOrNoneConvert, &error_code,
&usages,
&log))
return -1;
if ((super_kwds = PyDict_New()) == NULL) {
return -1;
}
if (error_message) {
if (PyDict_SetItemString(super_kwds, "error_message", PyString_FromString(error_message)) != 0) {
Py_DECREF(super_kwds);
return -1;
}
}
if (error_code != -1) {
if (PyDict_SetItemString(super_kwds, "error_code", PyInt_FromLong(error_code)) != 0) {
Py_DECREF(super_kwds);
return -1;
}
}
if ((result = CertVerifyErrorType.tp_base->tp_init((PyObject *)self, empty_tuple, super_kwds)) != 0) {
Py_DECREF(super_kwds);
return result;
}
self->usages = usages;
Py_CLEAR(self->log);
self->log = log;
Py_XINCREF(self->log);
return 0;
}
static PyTypeObject CertVerifyErrorType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"nss.error.CertVerifyError", /* tp_name */
sizeof(CertVerifyError), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)CertVerifyError_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(reprfunc)CertVerifyError_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
CertVerifyError_doc, /* tp_doc */
(traverseproc)CertVerifyError_traverse, /* tp_traverse */
(inquiry)CertVerifyError_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
CertVerifyError_members, /* tp_members */
0, /* tp_getset */
&NSPRErrorType, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)CertVerifyError_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
/* ============================== Module Exports ============================= */
static PyNSPR_ERROR_C_API_Type nspr_error_c_api =
{
NULL, /* nspr_exception */
set_nspr_error, /* set_nspr_error */
tuple_str
set_nspr_error,
set_cert_verify_error,
tuple_str,
lookup_nspr_error,
};
/* ============================== Module Construction ============================= */
@@ -317,6 +823,11 @@ initerror(void)
if ((m = Py_InitModule3("error", module_methods, module_doc)) == NULL)
return;
if ((empty_tuple = PyTuple_New(0)) == NULL) {
return;
}
Py_INCREF(empty_tuple);
if ((py_error_doc = init_py_nspr_errors(m)) == NULL)
return;
@@ -326,15 +837,13 @@ initerror(void)
PyString_ConcatAndDel(&py_module_doc, py_error_doc);
PyModule_AddObject(m, "__doc__", py_module_doc);
/* exceptions */
if ((NSPR_Exception = PyErr_NewException("nss.error.NSPRError", PyExc_EnvironmentError, NULL)) == NULL)
return;
Py_INCREF(NSPR_Exception);
if (PyModule_AddObject(m, "NSPRError", NSPR_Exception) < 0)
return;
NSPRErrorType.tp_base = (PyTypeObject *)PyExc_StandardError;
TYPE_READY(NSPRErrorType);
TYPE_READY(CertVerifyErrorType);
/* Export C API */
nspr_error_c_api.nspr_exception = NSPR_Exception;
nspr_error_c_api.nspr_exception = (PyObject *)&NSPRErrorType;
if (PyModule_AddObject(m, "_C_API", PyCObject_FromVoidPtr((void *)&nspr_error_c_api, NULL)) != 0)
return;

View File

@@ -2,15 +2,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdbool.h>
/* NSPR header files */
#undef HAVE_LONG_LONG /* FIXME: both Python.h and nspr.h define HAVE_LONG_LONG */
#include "nspr.h"
#include "prerror.h"
typedef struct {
PRErrorCode num;
const char *name;
const char *string;
} NSPRErrorDesc;
typedef struct {
PyObject *nspr_exception;
PyObject *(*set_nspr_error)(const char *format, ...);
PyObject *(*set_cert_verify_error)(unsigned int usages, PyObject * log, const char *format, ...);
PyObject *(*tuple_str)(PyObject *tuple);
const NSPRErrorDesc *(*lookup_nspr_error)(PRErrorCode num);
} PyNSPR_ERROR_C_API_Type;
#ifdef NSS_ERROR_MODULE
@@ -20,7 +30,9 @@ typedef struct {
static PyNSPR_ERROR_C_API_Type nspr_error_c_api;
#define set_nspr_error (*nspr_error_c_api.set_nspr_error)
#define set_cert_verify_error (*nspr_error_c_api.set_cert_verify_error)
#define tuple_str (*nspr_error_c_api.tuple_str)
#define lookup_nspr_error (*nspr_error_c_api.lookup_nspr_error)
static int
import_nspr_error_c_api(void)

View File

@@ -1719,7 +1719,7 @@ Socket_set_socket_option(Socket *self, PyObject *args)
{
PyObject *py_option = NULL;
int option;
int bool;
int boolean;
unsigned int uint;
NetworkAddress *mcaddr = NULL;
NetworkAddress *ifaddr = NULL;
@@ -1742,25 +1742,25 @@ Socket_set_socket_option(Socket *self, PyObject *args)
switch(option) {
case PR_SockOpt_Nonblocking:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.non_blocking = bool;
data.value.non_blocking = boolean;
break;
case PR_SockOpt_Linger:
if (!PyArg_ParseTuple(args, "iiI:set_socket_option", &option, &bool, &uint))
if (!PyArg_ParseTuple(args, "iiI:set_socket_option", &option, &boolean, &uint))
return NULL;
data.value.linger.polarity = bool;
data.value.linger.polarity = boolean;
data.value.linger.linger = uint;
break;
case PR_SockOpt_Reuseaddr:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.reuse_addr = bool;
data.value.reuse_addr = boolean;
break;
case PR_SockOpt_Keepalive:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.keep_alive = bool;
data.value.keep_alive = boolean;
break;
case PR_SockOpt_RecvBufferSize:
if (!PyArg_ParseTuple(args, "iI:set_socket_option", &option, &uint))
@@ -1810,14 +1810,14 @@ Socket_set_socket_option(Socket *self, PyObject *args)
data.value.mcast_ttl = uint;
break;
case PR_SockOpt_McastLoopback:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.mcast_loopback = bool;
data.value.mcast_loopback = boolean;
break;
case PR_SockOpt_NoDelay:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.no_delay = bool;
data.value.no_delay = boolean;
break;
case PR_SockOpt_MaxSegment:
if (!PyArg_ParseTuple(args, "iI:set_socket_option", &option, &uint))
@@ -1825,9 +1825,9 @@ Socket_set_socket_option(Socket *self, PyObject *args)
data.value.max_segment = uint;
break;
case PR_SockOpt_Broadcast:
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &bool))
if (!PyArg_ParseTuple(args, "ii:set_socket_option", &option, &boolean))
return NULL;
data.value.broadcast = bool;
data.value.broadcast = boolean;
break;
default:
PyErr_SetString(PyExc_ValueError, "set_socket_option: unknown option");

File diff suppressed because it is too large Load Diff

View File

@@ -355,6 +355,24 @@ typedef struct {
PyObject *py_decode_items; /* tuple */
} PKCS12Decoder;
/* ========================================================================== */
/* ========================== CertVerifyLogNode Class ======================= */
/* ========================================================================== */
typedef struct {
PyObject_HEAD
CERTVerifyLogNode node;
} CertVerifyLogNode;
/* ========================================================================== */
/* ============================ CertVerifyLog Class ========================= */
/* ========================================================================== */
typedef struct {
PyObject_HEAD
CERTVerifyLog log;
} CertVerifyLog;
/* ========================================================================== */
typedef struct {