|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/ChangeLog python-nss-0.14.1/doc/ChangeLog
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/ChangeLog 2013-05-02 17:29:27.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/ChangeLog 2013-10-09 09:35:29.000000000 -0400
|
|
 |
7f5c89 |
@@ -1,5 +1,37 @@
|
|
 |
7f5c89 |
-2013-04-24 John Dennis <jdennis@redhat.com> 0.14.0
|
|
 |
7f5c89 |
- External Changes
|
|
 |
7f5c89 |
+2013-10-09 John Dennis <jdennis@redhat.com> 0.14.1
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ Modifications only to tests and examples.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ * Fix bug in ssl_example.py and test_client_server.py where complete
|
|
 |
7f5c89 |
+ data was not read from socket. The Beast CVE fix in NSS causes
|
|
 |
7f5c89 |
+ only one octet to be sent in the first socket packet and then the
|
|
 |
7f5c89 |
+ remaining data is sent normally, this is known as 1/n-1 record
|
|
 |
7f5c89 |
+ splitting. The example and test SSL code sent short messages and
|
|
 |
7f5c89 |
+ then did a sock.recv(1024). We had always received the entire
|
|
 |
7f5c89 |
+ message in one sock.recv() call because it was so short. But
|
|
 |
7f5c89 |
+ sock.recv() does not guarantee how much data will be received,
|
|
 |
7f5c89 |
+ thus this was a coding mistake. The solution is straight forward,
|
|
 |
7f5c89 |
+ use newlines as a record separator and call sock.readline()
|
|
 |
7f5c89 |
+ instead of sock.recv(). sock.readline() calls sock.recv()
|
|
 |
7f5c89 |
+ internally until a complete line is read or the socket is closed.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ * Rewrite setup_certs.py, it was written like an expect script
|
|
 |
7f5c89 |
+ reacting to prompts read from a pseudo terminal but it was fragile
|
|
 |
7f5c89 |
+ and would hang on some systems. New version uses temporary
|
|
 |
7f5c89 |
+ password file and writes hardcoded responses to the stdin of
|
|
 |
7f5c89 |
+ certuil and modutil.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ * setup_certs now creates a new sql sytle NSS database (sql:pki)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ * All tests and examples now load the sql:pki database. Command line
|
|
 |
7f5c89 |
+ arg and variable changed from dbdir to db_name to reflect the
|
|
 |
7f5c89 |
+ database specification is no longer just a directory.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ * All command line process in test and examples now uses modern
|
|
 |
7f5c89 |
+ argparse module instead of deprecated getopt and optparse. Some
|
|
 |
7f5c89 |
+ command line args were tweaked.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+2013-04-24 John Dennis <jdennis@redhat.com> 0.14.0 External Changes
|
|
 |
7f5c89 |
----------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
The primary enhancements in this version is support of certifcate
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/examples/cert_dump.py python-nss-0.14.1/doc/examples/cert_dump.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/examples/cert_dump.py 2013-04-23 13:36:53.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/examples/cert_dump.py 2013-10-08 12:59:24.000000000 -0400
|
|
 |
7f5c89 |
@@ -18,10 +18,10 @@
|
|
 |
7f5c89 |
components of a cert.
|
|
 |
7f5c89 |
'''
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
+import getpass
|
|
 |
7f5c89 |
import os
|
|
 |
7f5c89 |
import sys
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import getpass
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
from nss.error import NSPRError
|
|
 |
7f5c89 |
import nss.io as io
|
|
 |
7f5c89 |
@@ -93,57 +93,34 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-usage_str = '''
|
|
 |
7f5c89 |
--p --pem read the certifcate in PEM ascii format (default)
|
|
 |
7f5c89 |
--d --der read the certifcate in DER binary format
|
|
 |
7f5c89 |
--P --print-cert print the cert using the internal rendering code
|
|
 |
7f5c89 |
-'''
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-def usage():
|
|
 |
7f5c89 |
- print usage_str
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-try:
|
|
 |
7f5c89 |
- opts, args = getopt.getopt(sys.argv[1:], "hpdP",
|
|
 |
7f5c89 |
- ["help", "pem", "der", "print-cert"])
|
|
 |
7f5c89 |
-except getopt.GetoptError:
|
|
 |
7f5c89 |
- # print help information and exit:
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit(2)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-filename = 'cert.der'
|
|
 |
7f5c89 |
-is_pem_format = True
|
|
 |
7f5c89 |
-print_cert = False
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-for o, a in opts:
|
|
 |
7f5c89 |
- if o in ("-H", "--help"):
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit()
|
|
 |
7f5c89 |
- elif o in ("-p", "--pem"):
|
|
 |
7f5c89 |
- is_pem_format = True
|
|
 |
7f5c89 |
- elif o in ("-d", "--der"):
|
|
 |
7f5c89 |
- is_pem_format = False
|
|
 |
7f5c89 |
- elif o in ("-P", "--print-cert"):
|
|
 |
7f5c89 |
- print_cert = True
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-filename = sys.argv[1]
|
|
 |
7f5c89 |
+parser = argparse.ArgumentParser(description='cert formatting example',
|
|
 |
7f5c89 |
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
 |
7f5c89 |
+parser.add_argument('-f', '--cert-format', choices=['pem', 'der'],
|
|
 |
7f5c89 |
+ help='format of input cert')
|
|
 |
7f5c89 |
+parser.add_argument('-p', '--print-cert', action='store_true',
|
|
 |
7f5c89 |
+ help='print the cert using the internal rendering code')
|
|
 |
7f5c89 |
+parser.add_argument('cert_file', nargs=1,
|
|
 |
7f5c89 |
+ help='input cert file to process')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.set_defaults(cert_format='pem',
|
|
 |
7f5c89 |
+ print_cert=False
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+options = parser.parse_args()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Perform basic configuration and setup
|
|
 |
7f5c89 |
nss.nss_init_nodb()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if len(args):
|
|
 |
7f5c89 |
- filename = args[0]
|
|
 |
7f5c89 |
+filename = options.cert_file[0]
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
print "certificate filename=%s" % (filename)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Read the certificate as DER encoded data
|
|
 |
7f5c89 |
-si = nss.read_der_from_file(filename, is_pem_format)
|
|
 |
7f5c89 |
+si = nss.read_der_from_file(filename, options.cert_format == 'pem')
|
|
 |
7f5c89 |
# Parse the DER encoded data returning a Certificate object
|
|
 |
7f5c89 |
cert = nss.Certificate(si)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Useful for comparing the internal cert rendering to what this script generates.
|
|
 |
7f5c89 |
-if print_cert:
|
|
 |
7f5c89 |
+if options.print_cert:
|
|
 |
7f5c89 |
print cert
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Get the extension list from the certificate
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/examples/httplib_example.py python-nss-0.14.1/doc/examples/httplib_example.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/examples/httplib_example.py 2013-04-15 13:05:46.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/examples/httplib_example.py 2013-10-08 13:04:03.000000000 -0400
|
|
 |
7f5c89 |
@@ -4,13 +4,13 @@
|
|
 |
7f5c89 |
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
 |
7f5c89 |
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-import sys
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
import errno
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import urlparse
|
|
 |
7f5c89 |
-import httplib
|
|
 |
7f5c89 |
import getpass
|
|
 |
7f5c89 |
+import httplib
|
|
 |
7f5c89 |
import logging
|
|
 |
7f5c89 |
+import sys
|
|
 |
7f5c89 |
+import urlparse
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
from nss.error import NSPRError
|
|
 |
7f5c89 |
import nss.io as io
|
|
 |
7f5c89 |
@@ -19,14 +19,6 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-httplib_debug_level = 0
|
|
 |
7f5c89 |
-logging_debug_level = logging.INFO
|
|
 |
7f5c89 |
-certdir = 'pki'
|
|
 |
7f5c89 |
-password = ''
|
|
 |
7f5c89 |
-nickname = ''
|
|
 |
7f5c89 |
-url = 'https://sourceforge.net/projects/python'
|
|
 |
7f5c89 |
-use_ssl = True
|
|
 |
7f5c89 |
-use_connection_class = True
|
|
 |
7f5c89 |
timeout_secs = 3
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#------------------------------------------------------------------------------
|
|
 |
7f5c89 |
@@ -94,28 +86,6 @@
|
|
 |
7f5c89 |
logging.debug('cert valid %s for "%s"', cert_is_valid, cert.subject)
|
|
 |
7f5c89 |
return cert_is_valid
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
|
|
 |
7f5c89 |
- cert = None
|
|
 |
7f5c89 |
- if chosen_nickname:
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- cert = nss.find_cert_from_nickname(chosen_nickname, password)
|
|
 |
7f5c89 |
- priv_key = nss.find_key_by_any_cert(cert, password)
|
|
 |
7f5c89 |
- return cert, priv_key
|
|
 |
7f5c89 |
- except NSPRError:
|
|
 |
7f5c89 |
- return False
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- nicknames = nss.get_cert_nicknames(certdb, nss.SEC_CERT_NICKNAMES_USER)
|
|
 |
7f5c89 |
- for nickname in nicknames:
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- cert = nss.find_cert_from_nickname(nickname, password)
|
|
 |
7f5c89 |
- if cert.check_valid_times():
|
|
 |
7f5c89 |
- if cert.has_signer_in_ca_names(ca_names):
|
|
 |
7f5c89 |
- priv_key = nss.find_key_by_any_cert(cert, password)
|
|
 |
7f5c89 |
- return cert, priv_key
|
|
 |
7f5c89 |
- except NSPRError:
|
|
 |
7f5c89 |
- return False
|
|
 |
7f5c89 |
- return False
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
def password_callback(slot, retry, password):
|
|
 |
7f5c89 |
if not retry and password: return password
|
|
 |
7f5c89 |
return getpass.getpass("Enter password for %s: " % slot.token_name);
|
|
 |
7f5c89 |
@@ -136,7 +106,7 @@
|
|
 |
7f5c89 |
if not dbdir:
|
|
 |
7f5c89 |
raise RuntimeError("dbdir is required")
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- logging.debug('%s init %s', self.__class__.__name__, host)
|
|
 |
7f5c89 |
+ logging.debug('%s init host=%s dbdir=%s', self.__class__.__name__, host, dbdir)
|
|
 |
7f5c89 |
if not nss.nss_is_initialized(): nss.nss_init(dbdir)
|
|
 |
7f5c89 |
self.sock = None
|
|
 |
7f5c89 |
ssl.set_domestic_policy()
|
|
 |
7f5c89 |
@@ -231,33 +201,46 @@
|
|
 |
7f5c89 |
#------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-opts, args = getopt.getopt(sys.argv[1:],
|
|
 |
7f5c89 |
- 'Dd:n:w:sScC',
|
|
 |
7f5c89 |
- ['debuglevel','certdir=','nickname=','password=',
|
|
 |
7f5c89 |
- 'use-ssl', 'no-ssl', 'use-connection-class', 'no-connection-class'])
|
|
 |
7f5c89 |
-for o, a in opts:
|
|
 |
7f5c89 |
- if o in('-D', '--httplib_debug_level'):
|
|
 |
7f5c89 |
- httplib_debug_level = httplib_debug_level + 1
|
|
 |
7f5c89 |
- elif o in ("-d", "--certdir"):
|
|
 |
7f5c89 |
- certdir = a
|
|
 |
7f5c89 |
- elif o in ("-n", "--nickname"):
|
|
 |
7f5c89 |
- nickname = a
|
|
 |
7f5c89 |
- elif o in ("-w", "--password"):
|
|
 |
7f5c89 |
- password = a
|
|
 |
7f5c89 |
- elif o in ("-s", "--use-ssl"):
|
|
 |
7f5c89 |
- use_ssl = True
|
|
 |
7f5c89 |
- elif o in ("-S", "--no-ssl"):
|
|
 |
7f5c89 |
- use_ssl = False
|
|
 |
7f5c89 |
- elif o in ("-c", "--use-connection-class"):
|
|
 |
7f5c89 |
- use_connection_class = True
|
|
 |
7f5c89 |
- elif o in ("-C", "--no-connection-class"):
|
|
 |
7f5c89 |
- use_connection_class = False
|
|
 |
7f5c89 |
+parser = argparse.ArgumentParser(description='httplib example')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if len(args) > 0:
|
|
 |
7f5c89 |
- url = args[0]
|
|
 |
7f5c89 |
+parser.add_argument('-d', '--db-name',
|
|
 |
7f5c89 |
+ help='NSS database name (e.g. "sql:pki")')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+parser.add_argument('--db-passwd',
|
|
 |
7f5c89 |
+ help='NSS database password')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if httplib_debug_level > 0:
|
|
 |
7f5c89 |
+parser.add_argument('-s', '--ssl', dest='use_ssl', action='store_true',
|
|
 |
7f5c89 |
+ help='use SSL connection')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-S', '--no-ssl', dest='use_ssl', action='store_false',
|
|
 |
7f5c89 |
+ help='do not use SSL connection')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-c', '--connection-class', dest='use_connection_class', action='store_true',
|
|
 |
7f5c89 |
+ help='use connection class')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-C', '--no-connection-class', dest='use_connection_class', action='store_false',
|
|
 |
7f5c89 |
+ help='do not use connection class')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-D', '--httplib-debug-level', action='count',
|
|
 |
7f5c89 |
+ help='httplib debug level')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('url', nargs=1,
|
|
 |
7f5c89 |
+ help='URL to open (e.g. "https://sourceforge.net/projects/python"')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.set_defaults(db_name = 'sql:pki',
|
|
 |
7f5c89 |
+ db_passwd = 'db_passwd',
|
|
 |
7f5c89 |
+ httplib_debug_level = 0,
|
|
 |
7f5c89 |
+ use_ssl = True,
|
|
 |
7f5c89 |
+ use_connection_class = True,
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+options = parser.parse_args()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+url = options.url[0]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+logging_debug_level = logging.INFO
|
|
 |
7f5c89 |
+if options.httplib_debug_level > 0:
|
|
 |
7f5c89 |
logging_debug_level = logging.DEBUG
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
logging_debug_level = logging.INFO
|
|
 |
7f5c89 |
@@ -269,7 +252,7 @@
|
|
 |
7f5c89 |
# Perform basic configuration and setup
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
url_components = urlparse.urlsplit(url)
|
|
 |
7f5c89 |
-if use_ssl:
|
|
 |
7f5c89 |
+if options.use_ssl:
|
|
 |
7f5c89 |
url_components.schema = 'https'
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
url_components.schema = 'http'
|
|
 |
7f5c89 |
@@ -280,14 +263,14 @@
|
|
 |
7f5c89 |
print "ERROR: bad url \"%s\"" % (url)
|
|
 |
7f5c89 |
sys.exit(1)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if use_connection_class:
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+if options.use_connection_class:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
logging.info("Start (using NSSConnection class) %s", url)
|
|
 |
7f5c89 |
- conn = NSSConnection(url_components.netloc, 443, dbdir="/etc/pki/nssdb")
|
|
 |
7f5c89 |
+ conn = NSSConnection(url_components.netloc, 443, dbdir=options.db_name)
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
logging.info("Start (using NSPRConnection class) %s", url)
|
|
 |
7f5c89 |
conn = NSPRConnection(url_components.netloc, 80)
|
|
 |
7f5c89 |
- conn.set_debuglevel(httplib_debug_level)
|
|
 |
7f5c89 |
+ conn.set_debuglevel(options.httplib_debug_level)
|
|
 |
7f5c89 |
conn.connect()
|
|
 |
7f5c89 |
conn.request("GET", "/")
|
|
 |
7f5c89 |
response = conn.getresponse()
|
|
 |
7f5c89 |
@@ -302,13 +285,13 @@
|
|
 |
7f5c89 |
print data
|
|
 |
7f5c89 |
conn.close()
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
logging.info("Start (using NSSHTTPS class) %s", url)
|
|
 |
7f5c89 |
- h = NSSHTTPS(url_components.netloc, 443, dbdir="/etc/pki/nssdb")
|
|
 |
7f5c89 |
+ h = NSSHTTPS(url_components.netloc, 443, dbdir=options.db_name)
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
logging.info("Start (using NSPRHTTP class) %s", url)
|
|
 |
7f5c89 |
h = NSPRHTTP(url_components.netloc, 80)
|
|
 |
7f5c89 |
- h.set_debuglevel(httplib_debug_level)
|
|
 |
7f5c89 |
+ h.set_debuglevel(options.httplib_debug_level)
|
|
 |
7f5c89 |
h.connect()
|
|
 |
7f5c89 |
h.putrequest('GET', '/')
|
|
 |
7f5c89 |
h.endheaders()
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/examples/ssl_example.py python-nss-0.14.1/doc/examples/ssl_example.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/examples/ssl_example.py 2013-04-15 13:05:46.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/examples/ssl_example.py 2013-10-09 00:07:54.000000000 -0400
|
|
 |
7f5c89 |
@@ -7,10 +7,10 @@
|
|
 |
7f5c89 |
import warnings
|
|
 |
7f5c89 |
warnings.simplefilter( "always", DeprecationWarning)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
+import getpass
|
|
 |
7f5c89 |
import os
|
|
 |
7f5c89 |
import sys
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import getpass
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
from nss.error import NSPRError
|
|
 |
7f5c89 |
import nss.io as io
|
|
 |
7f5c89 |
@@ -24,19 +24,7 @@
|
|
 |
7f5c89 |
REQUEST_CLIENT_CERT_ALWAYS = 3
|
|
 |
7f5c89 |
REQUIRE_CLIENT_CERT_ALWAYS = 4
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-# command line parameters, default them to something reasonable
|
|
 |
7f5c89 |
-client = False
|
|
 |
7f5c89 |
-server = False
|
|
 |
7f5c89 |
-password = 'db_passwd'
|
|
 |
7f5c89 |
-use_ssl = True
|
|
 |
7f5c89 |
-client_cert_action = NO_CLIENT_CERT
|
|
 |
7f5c89 |
-certdir = 'pki'
|
|
 |
7f5c89 |
-hostname = os.uname()[1]
|
|
 |
7f5c89 |
-server_nickname = 'test_server'
|
|
 |
7f5c89 |
-client_nickname = 'test_user'
|
|
 |
7f5c89 |
-port = 1234
|
|
 |
7f5c89 |
timeout_secs = 3
|
|
 |
7f5c89 |
-family = io.PR_AF_UNSPEC
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
# Utility Functions
|
|
 |
7f5c89 |
@@ -63,7 +51,7 @@
|
|
 |
7f5c89 |
if pin_args is None:
|
|
 |
7f5c89 |
pin_args = ()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- print "cert:\n%s" % cert
|
|
 |
7f5c89 |
+ print "peer cert:\n%s" % cert
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Define how the cert is being used based upon the is_server flag. This may
|
|
 |
7f5c89 |
# seem backwards, but isn't. If we're a server we're trying to validate a
|
|
 |
7f5c89 |
@@ -149,30 +137,30 @@
|
|
 |
7f5c89 |
valid_addr = False
|
|
 |
7f5c89 |
# Get the IP Address of our server
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
- addr_info = io.AddrInfo(hostname)
|
|
 |
7f5c89 |
+ addr_info = io.AddrInfo(options.hostname)
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
- print "could not resolve host address \"%s\"" % hostname
|
|
 |
7f5c89 |
+ print "could not resolve host address \"%s\"" % options.hostname
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
for net_addr in addr_info:
|
|
 |
7f5c89 |
- if family != io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
- if net_addr.family != family: continue
|
|
 |
7f5c89 |
- net_addr.port = port
|
|
 |
7f5c89 |
+ if options.family != io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
+ if net_addr.family != options.family: continue
|
|
 |
7f5c89 |
+ net_addr.port = options.port
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
sock = ssl.SSLSocket(net_addr.family)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Set client SSL socket options
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_SECURITY, True)
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
|
|
 |
7f5c89 |
- sock.set_hostname(hostname)
|
|
 |
7f5c89 |
+ sock.set_hostname(options.hostname)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Provide a callback which notifies us when the SSL handshake is complete
|
|
 |
7f5c89 |
sock.set_handshake_callback(handshake_callback)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Provide a callback to supply our client certificate info
|
|
 |
7f5c89 |
- sock.set_client_auth_data_callback(client_auth_data_callback, client_nickname,
|
|
 |
7f5c89 |
- password, nss.get_default_certdb())
|
|
 |
7f5c89 |
+ sock.set_client_auth_data_callback(client_auth_data_callback, options.client_nickname,
|
|
 |
7f5c89 |
+ options.password, nss.get_default_certdb())
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Provide a callback to verify the servers certificate
|
|
 |
7f5c89 |
sock.set_auth_certificate_callback(auth_certificate_callback,
|
|
 |
7f5c89 |
@@ -192,17 +180,18 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if not valid_addr:
|
|
 |
7f5c89 |
print "Could not establish valid address for \"%s\" in family %s" % \
|
|
 |
7f5c89 |
- (hostname, io.addr_family_name(family))
|
|
 |
7f5c89 |
+ (options.hostname, io.addr_family_name(options.family))
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Talk to the server
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
- sock.send("Hello")
|
|
 |
7f5c89 |
- buf = sock.recv(1024)
|
|
 |
7f5c89 |
+ sock.send('Hello' + '\n') # newline is protocol record separator
|
|
 |
7f5c89 |
+ buf = sock.readline()
|
|
 |
7f5c89 |
if not buf:
|
|
 |
7f5c89 |
print "client lost connection"
|
|
 |
7f5c89 |
sock.close()
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
+ buf = buf.rstrip() # remove newline record separator
|
|
 |
7f5c89 |
print "client received: %s" % (buf)
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print e.strerror
|
|
 |
7f5c89 |
@@ -221,7 +210,7 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
sock.close()
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
ssl.clear_session_cache()
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print e
|
|
 |
7f5c89 |
@@ -231,36 +220,34 @@
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def Server():
|
|
 |
7f5c89 |
- global family
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # Perform basic SSL server configuration
|
|
 |
7f5c89 |
- ssl.set_default_cipher_pref(ssl.SSL_RSA_WITH_NULL_MD5, True)
|
|
 |
7f5c89 |
- ssl.config_server_session_id_cache()
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # Get our certificate and private key
|
|
 |
7f5c89 |
- server_cert = nss.find_cert_from_nickname(server_nickname, password)
|
|
 |
7f5c89 |
- priv_key = nss.find_key_by_any_cert(server_cert, password)
|
|
 |
7f5c89 |
- server_cert_kea = server_cert.find_kea_type();
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- print "server cert:\n%s" % server_cert
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
# Setup an IP Address to listen on any of our interfaces
|
|
 |
7f5c89 |
- if family == io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
- family = io.PR_AF_INET
|
|
 |
7f5c89 |
- net_addr = io.NetworkAddress(io.PR_IpAddrAny, port, family)
|
|
 |
7f5c89 |
+ if options.family == io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
+ options.family = io.PR_AF_INET
|
|
 |
7f5c89 |
+ net_addr = io.NetworkAddress(io.PR_IpAddrAny, options.port, options.family)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
+ # Perform basic SSL server configuration
|
|
 |
7f5c89 |
+ ssl.set_default_cipher_pref(ssl.SSL_RSA_WITH_NULL_MD5, True)
|
|
 |
7f5c89 |
+ ssl.config_server_session_id_cache()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Get our certificate and private key
|
|
 |
7f5c89 |
+ server_cert = nss.find_cert_from_nickname(options.server_nickname, options.password)
|
|
 |
7f5c89 |
+ priv_key = nss.find_key_by_any_cert(server_cert, options.password)
|
|
 |
7f5c89 |
+ server_cert_kea = server_cert.find_kea_type();
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ print "server cert:\n%s" % server_cert
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
sock = ssl.SSLSocket(net_addr.family)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Set server SSL socket options
|
|
 |
7f5c89 |
- sock.set_pkcs11_pin_arg(password)
|
|
 |
7f5c89 |
+ sock.set_pkcs11_pin_arg(options.password)
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_SECURITY, True)
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_SERVER, True)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# If we're doing client authentication then set it up
|
|
 |
7f5c89 |
- if client_cert_action >= REQUEST_CLIENT_CERT_ONCE:
|
|
 |
7f5c89 |
+ if options.client_cert_action >= REQUEST_CLIENT_CERT_ONCE:
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_REQUEST_CERTIFICATE, True)
|
|
 |
7f5c89 |
- if client_cert_action == REQUIRE_CLIENT_CERT_ONCE:
|
|
 |
7f5c89 |
+ if options.client_cert_action == REQUIRE_CLIENT_CERT_ONCE:
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_REQUIRE_CERTIFICATE, True)
|
|
 |
7f5c89 |
sock.set_auth_certificate_callback(auth_certificate_callback, nss.get_default_certdb())
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -278,7 +265,7 @@
|
|
 |
7f5c89 |
while True:
|
|
 |
7f5c89 |
# Accept a connection from a client
|
|
 |
7f5c89 |
client_sock, client_addr = sock.accept()
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
client_sock.set_handshake_callback(handshake_callback)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
print "client connect from: %s" % (client_addr)
|
|
 |
7f5c89 |
@@ -286,14 +273,15 @@
|
|
 |
7f5c89 |
while True:
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
# Handle the client connection
|
|
 |
7f5c89 |
- buf = client_sock.recv(1024)
|
|
 |
7f5c89 |
+ buf = client_sock.readline()
|
|
 |
7f5c89 |
if not buf:
|
|
 |
7f5c89 |
print "server lost lost connection to %s" % (client_addr)
|
|
 |
7f5c89 |
break
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+ buf = buf.rstrip() # remove newline record separator
|
|
 |
7f5c89 |
print "server received: %s" % (buf)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- client_sock.send("Goodbye")
|
|
 |
7f5c89 |
+ client_sock.send('Goodbye' + '\n') # newline is protocol record separator
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
client_sock.shutdown(io.PR_SHUTDOWN_RCV)
|
|
 |
7f5c89 |
client_sock.close()
|
|
 |
7f5c89 |
@@ -308,7 +296,7 @@
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
sock.shutdown()
|
|
 |
7f5c89 |
sock.close()
|
|
 |
7f5c89 |
- if use_ssl:
|
|
 |
7f5c89 |
+ if options.use_ssl:
|
|
 |
7f5c89 |
ssl.shutdown_server_session_id_cache()
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print e
|
|
 |
7f5c89 |
@@ -316,141 +304,121 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-usage_str = '''
|
|
 |
7f5c89 |
--C --client run as the client (default: %(client)s)
|
|
 |
7f5c89 |
--S --server run as the server (default: %(server)s)
|
|
 |
7f5c89 |
--d --certdir certificate directory (default: %(certdir)s)
|
|
 |
7f5c89 |
--h --hostname host to connect to (default: %(hostname)s)
|
|
 |
7f5c89 |
--f --family may be inet|inet6|unspec (default: %(family)s)
|
|
 |
7f5c89 |
- if unspec client tries all addresses returned by AddrInfo
|
|
 |
7f5c89 |
- server binds to IPv4 "any" wildcard address
|
|
 |
7f5c89 |
- if inet client tries IPv4 addresses returned by AddrInfo
|
|
 |
7f5c89 |
- server binds to IPv4 "any" wildcard address
|
|
 |
7f5c89 |
- if inet6 client tries IPv6 addresses returned by AddrInfo
|
|
 |
7f5c89 |
- server binds to IPv6 "any" wildcard address
|
|
 |
7f5c89 |
--4 --inet set family to inet (see family)
|
|
 |
7f5c89 |
--6 --inet6 set family to inet6 (see family)
|
|
 |
7f5c89 |
--n --server_nickname server certificate nickname (default: %(server_nickname)s)
|
|
 |
7f5c89 |
--N --client_nickname client certificate nickname (default: %(client_nickname)s)
|
|
 |
7f5c89 |
--w --password certificate database password (default: %(password)s)
|
|
 |
7f5c89 |
--p --port host port (default: %(port)s)
|
|
 |
7f5c89 |
--e --encrypt use SSL (default) (default: %(encrypt)s)
|
|
 |
7f5c89 |
--E --noencrypt don't use SSL (default: %(noencrypt)s)
|
|
 |
7f5c89 |
--f --require_cert_once (default: %(require_cert_once)s)
|
|
 |
7f5c89 |
--F --require_cert_always (default: %(require_cert_always)s)
|
|
 |
7f5c89 |
--r --request_cert_once (default: %(request_cert_once)s)
|
|
 |
7f5c89 |
--R --request_cert_always (default: %(request_cert_always)s)
|
|
 |
7f5c89 |
--H --help
|
|
 |
7f5c89 |
-''' % {
|
|
 |
7f5c89 |
- 'client' : client,
|
|
 |
7f5c89 |
- 'server' : server,
|
|
 |
7f5c89 |
- 'certdir' : certdir,
|
|
 |
7f5c89 |
- 'hostname' : hostname,
|
|
 |
7f5c89 |
- 'family' : io.addr_family_name(family),
|
|
 |
7f5c89 |
- 'server_nickname' : server_nickname,
|
|
 |
7f5c89 |
- 'client_nickname' : client_nickname,
|
|
 |
7f5c89 |
- 'password' : password,
|
|
 |
7f5c89 |
- 'port' : port,
|
|
 |
7f5c89 |
- 'encrypt' : use_ssl is True,
|
|
 |
7f5c89 |
- 'noencrypt' : use_ssl is False,
|
|
 |
7f5c89 |
- 'require_cert_once' : client_cert_action == REQUIRE_CLIENT_CERT_ONCE,
|
|
 |
7f5c89 |
- 'require_cert_always' : client_cert_action == REQUIRE_CLIENT_CERT_ALWAYS,
|
|
 |
7f5c89 |
- 'request_cert_once' : client_cert_action == REQUEST_CLIENT_CERT_ONCE,
|
|
 |
7f5c89 |
- 'request_cert_always' : client_cert_action == REQUEST_CLIENT_CERT_ALWAYS,
|
|
 |
7f5c89 |
- }
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-def usage():
|
|
 |
7f5c89 |
- print usage_str
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-try:
|
|
 |
7f5c89 |
- opts, args = getopt.getopt(sys.argv[1:], "Hd:h:f:46n:N:w:p:CSeE",
|
|
 |
7f5c89 |
- ["help", "certdir=", "hostname=",
|
|
 |
7f5c89 |
- "family", "inet", "inet6",
|
|
 |
7f5c89 |
- "server_nickname=", "client_nickname=",
|
|
 |
7f5c89 |
- "password=", "port=",
|
|
 |
7f5c89 |
- "client", "server", "encrypt", "noencrypt",
|
|
 |
7f5c89 |
- "require_cert_once", "require_cert_always",
|
|
 |
7f5c89 |
- "request_cert_once", "request_cert_always",
|
|
 |
7f5c89 |
- ])
|
|
 |
7f5c89 |
-except getopt.GetoptError:
|
|
 |
7f5c89 |
- # print help information and exit:
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit(2)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-for o, a in opts:
|
|
 |
7f5c89 |
- if o in ("-d", "--certdir"):
|
|
 |
7f5c89 |
- certdir = a
|
|
 |
7f5c89 |
- elif o in ("-h", "--hostname"):
|
|
 |
7f5c89 |
- hostname = a
|
|
 |
7f5c89 |
- elif o in ("-f", "--family"):
|
|
 |
7f5c89 |
- if a == "inet":
|
|
 |
7f5c89 |
+class FamilyArgAction(argparse.Action):
|
|
 |
7f5c89 |
+ def __call__(self, parser, namespace, values, option_string=None):
|
|
 |
7f5c89 |
+ value = values[0]
|
|
 |
7f5c89 |
+ if value == "inet":
|
|
 |
7f5c89 |
family = io.PR_AF_INET
|
|
 |
7f5c89 |
- elif a == "inet6":
|
|
 |
7f5c89 |
+ elif value == "inet6":
|
|
 |
7f5c89 |
family = io.PR_AF_INET6
|
|
 |
7f5c89 |
- elif a == "unspec":
|
|
 |
7f5c89 |
+ elif value == "unspec":
|
|
 |
7f5c89 |
family = io.PR_AF_UNSPEC
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
- print "unknown address family (%s)" % (a)
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit()
|
|
 |
7f5c89 |
- elif o in ("-4", "--inet"):
|
|
 |
7f5c89 |
- family = io.PR_AF_INET
|
|
 |
7f5c89 |
- elif o in ("-6", "--inet6"):
|
|
 |
7f5c89 |
- family = io.PR_AF_INET6
|
|
 |
7f5c89 |
- elif o in ("-n", "--server_nickname"):
|
|
 |
7f5c89 |
- server_nickname = a
|
|
 |
7f5c89 |
- elif o in ("-N", "--client_nickname"):
|
|
 |
7f5c89 |
- client_nickname = a
|
|
 |
7f5c89 |
- elif o in ("-w", "--password"):
|
|
 |
7f5c89 |
- password = a
|
|
 |
7f5c89 |
- elif o in ("-p", "--port"):
|
|
 |
7f5c89 |
- port = int(a)
|
|
 |
7f5c89 |
- elif o in ("-C", "--client"):
|
|
 |
7f5c89 |
- client = True
|
|
 |
7f5c89 |
- elif o in ("-S", "--server"):
|
|
 |
7f5c89 |
- server = True
|
|
 |
7f5c89 |
- elif o in ("-e", "--encrypt"):
|
|
 |
7f5c89 |
- use_ssl = True
|
|
 |
7f5c89 |
- elif o in ("-E", "--noencrypt"):
|
|
 |
7f5c89 |
- use_ssl = False
|
|
 |
7f5c89 |
- elif o in ("--require_cert_once"):
|
|
 |
7f5c89 |
- client_cert_action = REQUIRE_CLIENT_CERT_ONCE
|
|
 |
7f5c89 |
- elif o in ("--require_cert_always"):
|
|
 |
7f5c89 |
- client_cert_action = REQUIRE_CLIENT_CERT_ALWAYS
|
|
 |
7f5c89 |
- elif o in ("--request_cert_once"):
|
|
 |
7f5c89 |
- client_cert_action = REQUEST_CLIENT_CERT_ONCE
|
|
 |
7f5c89 |
- elif o in ("--request_cert_always"):
|
|
 |
7f5c89 |
- client_cert_action = REQUEST_CLIENT_CERT_ALWAYS
|
|
 |
7f5c89 |
- elif o in ("-H", "--help"):
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit()
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit()
|
|
 |
7f5c89 |
+ raise argparse.ArgumentError(self, "unknown address family (%s)" % (value))
|
|
 |
7f5c89 |
+ setattr(namespace, self.dest, family)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser = argparse.ArgumentParser(description='SSL example')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-C', '--client', action='store_true',
|
|
 |
7f5c89 |
+ help='run as the client')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-S', '--server', action='store_true',
|
|
 |
7f5c89 |
+ help='run as the server')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-d', '--db-name',
|
|
 |
7f5c89 |
+ help='NSS database name (e.g. "sql:pki")')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-H', '--hostname',
|
|
 |
7f5c89 |
+ help='host to connect to')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-f', '--family',
|
|
 |
7f5c89 |
+ choices=['unspec', 'inet', 'inet6'],
|
|
 |
7f5c89 |
+ dest='family', action=FamilyArgAction, nargs=1,
|
|
 |
7f5c89 |
+ help='''
|
|
 |
7f5c89 |
+ If unspec client tries all addresses returned by AddrInfo,
|
|
 |
7f5c89 |
+ server binds to IPv4 "any" wildcard address.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ If inet client tries IPv4 addresses returned by AddrInfo,
|
|
 |
7f5c89 |
+ server binds to IPv4 "any" wildcard address.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ If inet6 client tries IPv6 addresses returned by AddrInfo,
|
|
 |
7f5c89 |
+ server binds to IPv6 "any" wildcard address''')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if client and server:
|
|
 |
7f5c89 |
+parser.add_argument('-4', '--inet',
|
|
 |
7f5c89 |
+ dest='family', action='store_const', const=io.PR_AF_INET,
|
|
 |
7f5c89 |
+ help='set family to inet (see family)')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-6', '--inet6',
|
|
 |
7f5c89 |
+ dest='family', action='store_const', const=io.PR_AF_INET6,
|
|
 |
7f5c89 |
+ help='set family to inet6 (see family)')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-n', '--server-nickname',
|
|
 |
7f5c89 |
+ help='server certificate nickname')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-N', '--client-nickname',
|
|
 |
7f5c89 |
+ help='client certificate nickname')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-w', '--password',
|
|
 |
7f5c89 |
+ help='certificate database password')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-p', '--port', type=int,
|
|
 |
7f5c89 |
+ help='host port')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-e', '--encrypt', dest='use_ssl', action='store_true',
|
|
 |
7f5c89 |
+ help='use SSL connection')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-E', '--no-encrypt', dest='use_ssl', action='store_false',
|
|
 |
7f5c89 |
+ help='do not use SSL connection')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('--require-cert-once', dest='client_cert_action',
|
|
 |
7f5c89 |
+ action='store_const', const=REQUIRE_CLIENT_CERT_ONCE)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('--require-cert-always', dest='client_cert_action',
|
|
 |
7f5c89 |
+ action='store_const', const=REQUIRE_CLIENT_CERT_ALWAYS)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('--request-cert-once', dest='client_cert_action',
|
|
 |
7f5c89 |
+ action='store_const', const=REQUEST_CLIENT_CERT_ONCE)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('--request-cert-always', dest='client_cert_action',
|
|
 |
7f5c89 |
+ action='store_const', const=REQUEST_CLIENT_CERT_ALWAYS)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.set_defaults(client = False,
|
|
 |
7f5c89 |
+ server = False,
|
|
 |
7f5c89 |
+ db_name = 'sql:pki',
|
|
 |
7f5c89 |
+ hostname = os.uname()[1],
|
|
 |
7f5c89 |
+ family = io.PR_AF_UNSPEC,
|
|
 |
7f5c89 |
+ server_nickname = 'test_server',
|
|
 |
7f5c89 |
+ client_nickname = 'test_user',
|
|
 |
7f5c89 |
+ password = 'db_passwd',
|
|
 |
7f5c89 |
+ port = 1234,
|
|
 |
7f5c89 |
+ use_ssl = True,
|
|
 |
7f5c89 |
+ client_cert_action = NO_CLIENT_CERT,
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+options = parser.parse_args()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+if options.client and options.server:
|
|
 |
7f5c89 |
print "can't be both client and server"
|
|
 |
7f5c89 |
sys.exit(1)
|
|
 |
7f5c89 |
-if not (client or server):
|
|
 |
7f5c89 |
+if not (options.client or options.server):
|
|
 |
7f5c89 |
print "must be one of client or server"
|
|
 |
7f5c89 |
sys.exit(1)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Perform basic configuration and setup
|
|
 |
7f5c89 |
-if certdir is None:
|
|
 |
7f5c89 |
- nss.nss_init_nodb()
|
|
 |
7f5c89 |
+if options.use_ssl:
|
|
 |
7f5c89 |
+ nss.nss_init(options.db_name)
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
- nss.nss_init(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init_nodb()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
ssl.set_domestic_policy()
|
|
 |
7f5c89 |
nss.set_password_callback(password_callback)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Run as a client or as a server
|
|
 |
7f5c89 |
-if client:
|
|
 |
7f5c89 |
+if options.client:
|
|
 |
7f5c89 |
print "starting as client"
|
|
 |
7f5c89 |
Client()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-if server:
|
|
 |
7f5c89 |
+if options.server:
|
|
 |
7f5c89 |
print "starting as server"
|
|
 |
7f5c89 |
Server()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -458,4 +426,3 @@
|
|
 |
7f5c89 |
nss.nss_shutdown()
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print e
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/examples/verify_cert.py python-nss-0.14.1/doc/examples/verify_cert.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/examples/verify_cert.py 2013-04-15 13:05:46.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/examples/verify_cert.py 2013-10-08 13:04:51.000000000 -0400
|
|
 |
7f5c89 |
@@ -1,7 +1,7 @@
|
|
 |
7f5c89 |
#!/usr/bin/python
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
import sys
|
|
 |
7f5c89 |
-import optparse
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
import nss.nss as nss
|
|
 |
7f5c89 |
import nss.error as nss_error
|
|
 |
7f5c89 |
@@ -75,75 +75,74 @@
|
|
 |
7f5c89 |
lines.extend(nss.make_line_fmt_tuples(level, msg))
|
|
 |
7f5c89 |
lines.extend(obj.format_lines(level+1))
|
|
 |
7f5c89 |
return nss.indented_format(lines)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def main():
|
|
 |
7f5c89 |
- # Command line argument processing
|
|
 |
7f5c89 |
- parser = optparse.OptionParser()
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- parser.set_defaults(dbdir = '/etc/pki/nssdb',
|
|
 |
7f5c89 |
- db_passwd = 'db_passwd',
|
|
 |
7f5c89 |
- input_format = 'pem',
|
|
 |
7f5c89 |
- check_sig = True,
|
|
 |
7f5c89 |
- print_cert = False,
|
|
 |
7f5c89 |
- with_log = True,
|
|
 |
7f5c89 |
- check_ca = True,
|
|
 |
7f5c89 |
- )
|
|
 |
7f5c89 |
+ global options
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group = optparse.OptionGroup(parser, 'NSS Database',
|
|
 |
7f5c89 |
- 'Specify & control the NSS Database')
|
|
 |
7f5c89 |
+ parser = argparse.ArgumentParser(description='certificate validation example')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group.add_option('-d', '--dbdir', dest='dbdir',
|
|
 |
7f5c89 |
- help='NSS database directory, default="%default"')
|
|
 |
7f5c89 |
- param_group.add_option('-P', '--db-passwd', dest='db_passwd',
|
|
 |
7f5c89 |
- help='NSS database password, default="%default"')
|
|
 |
7f5c89 |
+ # === NSS Database Group ===
|
|
 |
7f5c89 |
+ group = parser.add_argument_group('NSS Database',
|
|
 |
7f5c89 |
+ 'Specify & control the NSS Database')
|
|
 |
7f5c89 |
+ group.add_argument('-d', '--db-name',
|
|
 |
7f5c89 |
+ help='NSS database name (e.g. "sql:pki")')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- parser.add_option_group(param_group)
|
|
 |
7f5c89 |
+ group.add_argument('-P', '--db-passwd',
|
|
 |
7f5c89 |
+ help='NSS database password')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group = optparse.OptionGroup(parser, 'Certificate',
|
|
 |
7f5c89 |
- 'Specify how the certificate is loaded')
|
|
 |
7f5c89 |
+ # === Certificate Group ===
|
|
 |
7f5c89 |
+ group = parser.add_argument_group('Certificate',
|
|
 |
7f5c89 |
+ 'Specify how the certificate is loaded')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group.add_option('-f', '--file', dest='cert_filename',
|
|
 |
7f5c89 |
- help='read cert from file')
|
|
 |
7f5c89 |
- param_group.add_option('--format', dest='input_format', choices=['pem', 'der'],
|
|
 |
7f5c89 |
- help='import format for certificate (der|pem) default="%default"')
|
|
 |
7f5c89 |
- param_group.add_option('-n', '--nickname', dest='cert_nickname',
|
|
 |
7f5c89 |
- help='load cert from NSS database by looking it up under this nickname')
|
|
 |
7f5c89 |
+ group.add_argument('-f', '--file', dest='cert_filename',
|
|
 |
7f5c89 |
+ help='read cert from file')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+ group.add_argument('-F', '--input-format', choices=['pem', 'der'],
|
|
 |
7f5c89 |
+ help='format of input cert')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- parser.add_option_group(param_group)
|
|
 |
7f5c89 |
+ group.add_argument('-n', '--nickname', dest='cert_nickname',
|
|
 |
7f5c89 |
+ help='load cert from NSS database by looking it up under this nickname')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group = optparse.OptionGroup(parser, 'Validation',
|
|
 |
7f5c89 |
- 'Control the validation')
|
|
 |
7f5c89 |
+ # === Validation Group ===
|
|
 |
7f5c89 |
+ group = parser.add_argument_group('Validation',
|
|
 |
7f5c89 |
+ 'Control the validation')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group.add_option('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
|
|
 |
7f5c89 |
- help='may be specified multiple times, default="CheckAllUsages", may be one of: %s' % ', '.join(sorted(cert_usage_map.keys())))
|
|
 |
7f5c89 |
- param_group.add_option('-c', '--check-sig', action='store_true', dest='check_sig',
|
|
 |
7f5c89 |
- help='check signature default=%default')
|
|
 |
7f5c89 |
- param_group.add_option('-C', '--no-check-sig', action='store_false', dest='check_sig',
|
|
 |
7f5c89 |
+ group.add_argument('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
|
|
 |
7f5c89 |
+ help='certificate usage flags, may be specified multiple times')
|
|
 |
7f5c89 |
+ group.add_argument('-c', '--check-sig', action='store_true', dest='check_sig',
|
|
 |
7f5c89 |
help='check signature')
|
|
 |
7f5c89 |
- param_group.add_option('-l', '--log', action='store_true', dest='with_log',
|
|
 |
7f5c89 |
- help='use verify log, default=%default')
|
|
 |
7f5c89 |
- param_group.add_option('-L', '--no-log', action='store_false', dest='with_log',
|
|
 |
7f5c89 |
- help='use verify log, default=%default')
|
|
 |
7f5c89 |
- param_group.add_option('-a', '--check-ca', action='store_true', dest='check_ca',
|
|
 |
7f5c89 |
- help='check if cert is CA, default=%default')
|
|
 |
7f5c89 |
- param_group.add_option('-A', '--no-check-ca', action='store_false', dest='check_ca',
|
|
 |
7f5c89 |
- help='check if cert is CA, default=%default')
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- parser.add_option_group(param_group)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- param_group = optparse.OptionGroup(parser, 'Miscellaneous',
|
|
 |
7f5c89 |
- 'Miscellaneous options')
|
|
 |
7f5c89 |
+ group.add_argument('-C', '--no-check-sig', action='store_false', dest='check_sig',
|
|
 |
7f5c89 |
+ help='do not check signature')
|
|
 |
7f5c89 |
+ group.add_argument('-l', '--log', action='store_true', dest='with_log',
|
|
 |
7f5c89 |
+ help='use verify log')
|
|
 |
7f5c89 |
+ group.add_argument('-L', '--no-log', action='store_false', dest='with_log',
|
|
 |
7f5c89 |
+ help='do not use verify log')
|
|
 |
7f5c89 |
+ group.add_argument('-a', '--check-ca', action='store_true', dest='check_ca',
|
|
 |
7f5c89 |
+ help='check if cert is CA')
|
|
 |
7f5c89 |
+ group.add_argument('-A', '--no-check-ca', action='store_false', dest='check_ca',
|
|
 |
7f5c89 |
+ help='do not check if cert is CA')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # === Miscellaneous Group ===
|
|
 |
7f5c89 |
+ group = parser.add_argument_group('Miscellaneous',
|
|
 |
7f5c89 |
+ 'Miscellaneous options')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- param_group.add_option('-p', '--print-cert', action='store_true', dest='print_cert',
|
|
 |
7f5c89 |
- help='print the certificate in a friendly fashion, default=%default')
|
|
 |
7f5c89 |
+ group.add_argument('-p', '--print-cert', action='store_true', dest='print_cert',
|
|
 |
7f5c89 |
+ help='print the certificate in a friendly fashion')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- parser.add_option_group(param_group)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- options, args = parser.parse_args()
|
|
 |
7f5c89 |
+ parser.set_defaults(db_name = 'sql:pki',
|
|
 |
7f5c89 |
+ db_passwd = 'db_passwd',
|
|
 |
7f5c89 |
+ input_format = 'pem',
|
|
 |
7f5c89 |
+ check_sig = True,
|
|
 |
7f5c89 |
+ with_log = True,
|
|
 |
7f5c89 |
+ check_ca = True,
|
|
 |
7f5c89 |
+ print_cert = False,
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ options = parser.parse_args()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Process the command line arguments
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -175,9 +174,9 @@
|
|
 |
7f5c89 |
return 1
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Initialize NSS.
|
|
 |
7f5c89 |
- print indented_output('NSS Database', options.dbdir)
|
|
 |
7f5c89 |
+ print indented_output('NSS Database', options.db_name)
|
|
 |
7f5c89 |
print
|
|
 |
7f5c89 |
- nss.nss_init(options.dbdir)
|
|
 |
7f5c89 |
+ nss.nss_init(options.db_name)
|
|
 |
7f5c89 |
certdb = nss.get_default_certdb()
|
|
 |
7f5c89 |
nss.set_password_callback(password_callback)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -194,7 +193,7 @@
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print e
|
|
 |
7f5c89 |
print >>sys.stderr, 'Unable to load cert nickname "%s" from database "%s"' % \
|
|
 |
7f5c89 |
- (options.cert_nickname, options.dbdir)
|
|
 |
7f5c89 |
+ (options.cert_nickname, options.db_name)
|
|
 |
7f5c89 |
return 1
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Dump the cert if the user wants to see it
|
|
 |
7f5c89 |
@@ -282,5 +281,3 @@
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
if __name__ == "__main__":
|
|
 |
7f5c89 |
sys.exit(main())
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/doc/examples/verify_server.py python-nss-0.14.1/doc/examples/verify_server.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/doc/examples/verify_server.py 2013-04-15 13:05:46.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/doc/examples/verify_server.py 2013-10-08 13:00:37.000000000 -0400
|
|
 |
7f5c89 |
@@ -4,10 +4,10 @@
|
|
 |
7f5c89 |
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
 |
7f5c89 |
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
+import getpass
|
|
 |
7f5c89 |
import os
|
|
 |
7f5c89 |
import sys
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import getpass
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
from nss.error import NSPRError
|
|
 |
7f5c89 |
import nss.io as io
|
|
 |
7f5c89 |
@@ -16,11 +16,6 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-# command line parameters, default them to something reasonable
|
|
 |
7f5c89 |
-#certdir = '/etc/httpd/alias'
|
|
 |
7f5c89 |
-certdir = '/etc/pki/nssdb'
|
|
 |
7f5c89 |
-hostname = 'www.verisign.com'
|
|
 |
7f5c89 |
-port = 443
|
|
 |
7f5c89 |
timeout_secs = 3
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
request = '''\
|
|
 |
7f5c89 |
@@ -104,18 +99,18 @@
|
|
 |
7f5c89 |
valid_addr = False
|
|
 |
7f5c89 |
# Get the IP Address of our server
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
- addr_info = io.AddrInfo(hostname)
|
|
 |
7f5c89 |
+ addr_info = io.AddrInfo(options.hostname)
|
|
 |
7f5c89 |
except:
|
|
 |
7f5c89 |
- print "ERROR: could not resolve hostname \"%s\"" % hostname
|
|
 |
7f5c89 |
+ print "ERROR: could not resolve hostname \"%s\"" % options.hostname
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
for net_addr in addr_info:
|
|
 |
7f5c89 |
- net_addr.port = port
|
|
 |
7f5c89 |
+ net_addr.port = options.port
|
|
 |
7f5c89 |
sock = ssl.SSLSocket(net_addr.family)
|
|
 |
7f5c89 |
# Set client SSL socket options
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_SECURITY, True)
|
|
 |
7f5c89 |
sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
|
|
 |
7f5c89 |
- sock.set_hostname(hostname)
|
|
 |
7f5c89 |
+ sock.set_hostname(options.hostname)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Provide a callback which notifies us when the SSL handshake is
|
|
 |
7f5c89 |
# complete
|
|
 |
7f5c89 |
@@ -135,7 +130,7 @@
|
|
 |
7f5c89 |
continue
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if not valid_addr:
|
|
 |
7f5c89 |
- print "ERROR: could not connect to \"%s\"" % hostname
|
|
 |
7f5c89 |
+ print "ERROR: could not connect to \"%s\"" % options.hostname
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
@@ -158,48 +153,31 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-usage_str = '''
|
|
 |
7f5c89 |
--d --certdir certificate directory (default: %(certdir)s)
|
|
 |
7f5c89 |
--h --hostname host to connect to (default: %(hostname)s)
|
|
 |
7f5c89 |
--p --port host port (default: %(port)s)
|
|
 |
7f5c89 |
-''' % {
|
|
 |
7f5c89 |
- 'certdir' : certdir,
|
|
 |
7f5c89 |
- 'hostname' : hostname,
|
|
 |
7f5c89 |
- 'port' : port,
|
|
 |
7f5c89 |
- }
|
|
 |
7f5c89 |
+parser = argparse.ArgumentParser(description='certificate verification example',
|
|
 |
7f5c89 |
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def usage():
|
|
 |
7f5c89 |
- print usage_str
|
|
 |
7f5c89 |
+parser.add_argument('-d', '--db-name',
|
|
 |
7f5c89 |
+ help='NSS database name (e.g. "sql:pki")')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-try:
|
|
 |
7f5c89 |
- opts, args = getopt.getopt(sys.argv[1:], "Hd:h:p:",
|
|
 |
7f5c89 |
- ["help", "certdir=", "hostname=",
|
|
 |
7f5c89 |
- "port=",
|
|
 |
7f5c89 |
- ])
|
|
 |
7f5c89 |
-except getopt.GetoptError:
|
|
 |
7f5c89 |
- # print help information and exit:
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit(2)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-for o, a in opts:
|
|
 |
7f5c89 |
- if o in ("-d", "--certdir"):
|
|
 |
7f5c89 |
- certdir = a
|
|
 |
7f5c89 |
- if o in ("-h", "--hostname"):
|
|
 |
7f5c89 |
- hostname = a
|
|
 |
7f5c89 |
- if o in ("-p", "--port"):
|
|
 |
7f5c89 |
- port = int(a)
|
|
 |
7f5c89 |
- if o in ("-H", "--help"):
|
|
 |
7f5c89 |
- usage()
|
|
 |
7f5c89 |
- sys.exit()
|
|
 |
7f5c89 |
+parser.add_argument('-H', '--hostname',
|
|
 |
7f5c89 |
+ help='host to connect to')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.add_argument('-p', '--port', type=int,
|
|
 |
7f5c89 |
+ help='host port')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+parser.set_defaults(db_name = 'sql:pki',
|
|
 |
7f5c89 |
+ hostname = 'www.verisign.com',
|
|
 |
7f5c89 |
+ port = 443,
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+options = parser.parse_args()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Perform basic configuration and setup
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
- nss.nss_init(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init(options.db_name)
|
|
 |
7f5c89 |
ssl.set_domestic_policy()
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print >>sys.stderr, e.strerror
|
|
 |
7f5c89 |
sys.exit(1)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
client()
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/src/__init__.py python-nss-0.14.1/src/__init__.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/src/__init__.py 2013-04-24 16:30:26.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/src/__init__.py 2013-10-08 14:38:28.000000000 -0400
|
|
 |
7f5c89 |
@@ -163,8 +163,8 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- Initialize NSS and indicate the certficate database (CertDB)::
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- certdir = './pki'
|
|
 |
7f5c89 |
- ssl.nssinit(certdir)
|
|
 |
7f5c89 |
+ db_name = 'sql:pki'
|
|
 |
7f5c89 |
+ ssl.nssinit(db_name)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- If you are implementing an SSL server call config_secure_server()
|
|
 |
7f5c89 |
(see ssl_example.py)::
|
|
 |
7f5c89 |
@@ -244,7 +244,7 @@
|
|
 |
7f5c89 |
future we can find a solution but the immediate goal of the NSS
|
|
 |
7f5c89 |
Python binding was to expose NSS through Python, not necessarily
|
|
 |
7f5c89 |
to solve the larger integration issue of Python run-time and NSPR
|
|
 |
7f5c89 |
- run-time.
|
|
 |
7f5c89 |
+ run-time.
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- NSPR would like to hide the underlying platform socket (in the
|
|
 |
7f5c89 |
NSPR code this is called "osfd"). There are NSPR API's which
|
|
 |
7f5c89 |
@@ -312,5 +312,4 @@
|
|
 |
7f5c89 |
To be added
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
"""
|
|
 |
7f5c89 |
-__version__ = '0.14.0'
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
+__version__ = '0.14.1'
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/run_tests python-nss-0.14.1/test/run_tests
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/run_tests 2013-04-30 11:03:54.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/run_tests 2013-10-08 12:57:56.000000000 -0400
|
|
 |
7f5c89 |
@@ -1,21 +1,13 @@
|
|
 |
7f5c89 |
#!/usr/bin/python
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import sys
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
import os
|
|
 |
7f5c89 |
+import sys
|
|
 |
7f5c89 |
import unittest
|
|
 |
7f5c89 |
from util import get_build_dir
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-prog_name = os.path.basename(sys.argv[0])
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-config = {
|
|
 |
7f5c89 |
- 'in_tree' : True,
|
|
 |
7f5c89 |
-}
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
def run_tests():
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
import setup_certs
|
|
 |
7f5c89 |
@@ -23,9 +15,11 @@
|
|
 |
7f5c89 |
import test_cipher
|
|
 |
7f5c89 |
import test_digest
|
|
 |
7f5c89 |
import test_pkcs12
|
|
 |
7f5c89 |
+ import test_misc
|
|
 |
7f5c89 |
+ import test_ocsp
|
|
 |
7f5c89 |
import test_client_server
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- setup_certs.setup_certs()
|
|
 |
7f5c89 |
+ setup_certs.setup_certs([])
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
loader = unittest.TestLoader()
|
|
 |
7f5c89 |
runner = unittest.TextTestRunner()
|
|
 |
7f5c89 |
@@ -43,62 +37,19 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-class Usage(Exception):
|
|
 |
7f5c89 |
- def __init__(self, msg):
|
|
 |
7f5c89 |
- self.msg = msg
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-def usage():
|
|
 |
7f5c89 |
- 'Print command help.'
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- return '''\
|
|
 |
7f5c89 |
-%(prog_name)s [-i]
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
--h --help print help
|
|
 |
7f5c89 |
--i --installed runs the test using installed libraries
|
|
 |
7f5c89 |
- instead of "in tree" libraries
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-Runs unit tests.
|
|
 |
7f5c89 |
-By default test is done "in tree".
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-Examples:
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-Run test using libraries built in this tree
|
|
 |
7f5c89 |
-%(prog_name)s
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-Run post install test
|
|
 |
7f5c89 |
-%(prog_name)s -i
|
|
 |
7f5c89 |
-''' % {'prog_name' : prog_name,
|
|
 |
7f5c89 |
- }
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
+def main():
|
|
 |
7f5c89 |
+ parser = argparse.ArgumentParser(description='run the units (installed or in tree)')
|
|
 |
7f5c89 |
+ parser.add_argument('-i', '--installed', action='store_false', dest='in_tree',
|
|
 |
7f5c89 |
+ help='run tests using installed library')
|
|
 |
7f5c89 |
+ parser.add_argument('-t', '--in-tree', action='store_true', dest='in_tree',
|
|
 |
7f5c89 |
+ help='run tests using devel tree')
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def main(argv=None):
|
|
 |
7f5c89 |
- if argv is None:
|
|
 |
7f5c89 |
- argv = sys.argv
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- opts, args = getopt.getopt(argv[1:], 'hi',
|
|
 |
7f5c89 |
- ['help', 'installed',])
|
|
 |
7f5c89 |
- except getopt.GetoptError, e:
|
|
 |
7f5c89 |
- raise Usage(e)
|
|
 |
7f5c89 |
- return 2
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- for o, a in opts:
|
|
 |
7f5c89 |
- if o in ('-h', '--help'):
|
|
 |
7f5c89 |
- print >>sys.stdout, usage()
|
|
 |
7f5c89 |
- return 0
|
|
 |
7f5c89 |
- elif o in ('-i', '--installed'):
|
|
 |
7f5c89 |
- config['in_tree'] = False
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- raise Usage("command argument '%s' not handled, internal error" % o)
|
|
 |
7f5c89 |
- except Usage, e:
|
|
 |
7f5c89 |
- print >>sys.stderr, e.msg
|
|
 |
7f5c89 |
- print >>sys.stderr, "for help use --help"
|
|
 |
7f5c89 |
- return 2
|
|
 |
7f5c89 |
+ parser.set_defaults(in_tree = False,
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+ options = parser.parse_args()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- if config['in_tree']:
|
|
 |
7f5c89 |
+ if options.in_tree:
|
|
 |
7f5c89 |
# Run the tests "in the tree"
|
|
 |
7f5c89 |
# Rather than testing with installed versions run the test
|
|
 |
7f5c89 |
# with the package built in this tree.
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/setup_certs.py python-nss-0.14.1/test/setup_certs.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/setup_certs.py 2013-04-18 12:28:05.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/setup_certs.py 2013-10-17 11:07:09.000000000 -0400
|
|
 |
7f5c89 |
@@ -1,345 +1,506 @@
|
|
 |
7f5c89 |
#!/usr/bin/python
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-import traceback
|
|
 |
7f5c89 |
-import getopt
|
|
 |
7f5c89 |
-import sys
|
|
 |
7f5c89 |
-import os
|
|
 |
7f5c89 |
-import errno
|
|
 |
7f5c89 |
+import argparse
|
|
 |
7f5c89 |
+import atexit
|
|
 |
7f5c89 |
import logging
|
|
 |
7f5c89 |
-import subprocess
|
|
 |
7f5c89 |
+import os
|
|
 |
7f5c89 |
import shutil
|
|
 |
7f5c89 |
-import shlex
|
|
 |
7f5c89 |
-import pty
|
|
 |
7f5c89 |
-import tty
|
|
 |
7f5c89 |
-import re
|
|
 |
7f5c89 |
-import time
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-__all__ = ["config", "setup_certs"]
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-if __name__ == '__main__':
|
|
 |
7f5c89 |
- prog_name = os.path.basename(sys.argv[0])
|
|
 |
7f5c89 |
-else:
|
|
 |
7f5c89 |
- prog_name = 'setup_certs'
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-serial_number = 0
|
|
 |
7f5c89 |
-hostname = os.uname()[1]
|
|
 |
7f5c89 |
-client_username = 'test_user'
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-config = {
|
|
 |
7f5c89 |
- 'verbose' : False,
|
|
 |
7f5c89 |
- 'debug' : False,
|
|
 |
7f5c89 |
- 'logfile' : 'setup_certs.log',
|
|
 |
7f5c89 |
- 'log_level' : logging.WARN,
|
|
 |
7f5c89 |
- 'interactive' : sys.stdout.isatty(),
|
|
 |
7f5c89 |
- 'dbdir' : os.path.join(os.path.dirname(sys.argv[0]), 'pki'),
|
|
 |
7f5c89 |
- 'db_passwd' : 'db_passwd',
|
|
 |
7f5c89 |
- 'noise_file' : 'noise_file',
|
|
 |
7f5c89 |
- 'ca_subject' : 'CN=Test CA',
|
|
 |
7f5c89 |
- 'ca_nickname' : 'test_ca',
|
|
 |
7f5c89 |
- 'server_subject' : 'CN=%s' % hostname,
|
|
 |
7f5c89 |
- 'server_nickname' : 'test_server',
|
|
 |
7f5c89 |
- 'client_subject' : 'CN=%s' % client_username,
|
|
 |
7f5c89 |
- 'client_nickname' : client_username,
|
|
 |
7f5c89 |
-}
|
|
 |
7f5c89 |
+import subprocess
|
|
 |
7f5c89 |
+import sys
|
|
 |
7f5c89 |
+from string import Template
|
|
 |
7f5c89 |
+import tempfile
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
class CmdError(Exception):
|
|
 |
7f5c89 |
- def __init__(self, cmd, exit_code, msg):
|
|
 |
7f5c89 |
- self.cmd = cmd
|
|
 |
7f5c89 |
- self.exit_code = exit_code
|
|
 |
7f5c89 |
- self.msg = msg
|
|
 |
7f5c89 |
+ def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None):
|
|
 |
7f5c89 |
+ self.cmd_args = cmd_args
|
|
 |
7f5c89 |
+ self.returncode = returncode
|
|
 |
7f5c89 |
+ if message is None:
|
|
 |
7f5c89 |
+ self.message = 'Failed error=%s, ' % (returncode)
|
|
 |
7f5c89 |
+ if stderr:
|
|
 |
7f5c89 |
+ self.message += '"%s", ' % stderr
|
|
 |
7f5c89 |
+ self.message += 'args=%s' % (cmd_args)
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ self.message = message
|
|
 |
7f5c89 |
+ self.stdout = stdout
|
|
 |
7f5c89 |
+ self.stderr = stderr
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def __str__(self):
|
|
 |
7f5c89 |
- return "Command \"%s\"\nFailed with exit code = %s\nOutput was:\n%s\n" % \
|
|
 |
7f5c89 |
- (self.cmd, self.exit_code, self.msg)
|
|
 |
7f5c89 |
+ return self.message
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def next_serial():
|
|
 |
7f5c89 |
- global serial_number
|
|
 |
7f5c89 |
- serial_number += 1
|
|
 |
7f5c89 |
- return serial_number
|
|
 |
7f5c89 |
+def run_cmd(cmd_args, input=None):
|
|
 |
7f5c89 |
+ logging.debug(' '.join(cmd_args))
|
|
 |
7f5c89 |
+ try:
|
|
 |
7f5c89 |
+ p = subprocess.Popen(cmd_args,
|
|
 |
7f5c89 |
+ stdin=subprocess.PIPE,
|
|
 |
7f5c89 |
+ stdout=subprocess.PIPE,
|
|
 |
7f5c89 |
+ stderr=subprocess.PIPE)
|
|
 |
7f5c89 |
+ stdout, stderr = p.communicate(input)
|
|
 |
7f5c89 |
+ returncode = p.returncode
|
|
 |
7f5c89 |
+ if returncode != 0:
|
|
 |
7f5c89 |
+ raise CmdError(cmd_args, returncode,
|
|
 |
7f5c89 |
+ 'failed %s' % (', '.join(cmd_args)),
|
|
 |
7f5c89 |
+ stdout, stderr)
|
|
 |
7f5c89 |
+ return stdout, stderr
|
|
 |
7f5c89 |
+ except OSError as e:
|
|
 |
7f5c89 |
+ raise CmdError(cmd_args, e.errno, stderr=str(e))
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def exit_handler(options):
|
|
 |
7f5c89 |
+ logging.debug('in exit handler')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ if options.passwd_filename is not None:
|
|
 |
7f5c89 |
+ logging.debug('removing passwd_filename=%s', options.passwd_filename)
|
|
 |
7f5c89 |
+ os.remove(options.passwd_filename)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ if options.noise_filename is not None:
|
|
 |
7f5c89 |
+ logging.debug('removing noise_filename=%s', options.noise_filename)
|
|
 |
7f5c89 |
+ os.remove(options.noise_filename)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def write_serial(options, serial_number):
|
|
 |
7f5c89 |
+ with open(options.serial_file, 'w') as f:
|
|
 |
7f5c89 |
+ f.write('%x\n' % serial_number)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def read_serial(options):
|
|
 |
7f5c89 |
+ if not os.path.exists(options.serial_file):
|
|
 |
7f5c89 |
+ write_serial(options, options.serial_number)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def create_noise_file():
|
|
 |
7f5c89 |
- """
|
|
 |
7f5c89 |
- Generate a noise file to be used when creating a key
|
|
 |
7f5c89 |
- """
|
|
 |
7f5c89 |
- if os.path.exists(config['noise_file']):
|
|
 |
7f5c89 |
- os.remove(config['noise_file'])
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- f = open(config['noise_file'], "w")
|
|
 |
7f5c89 |
- f.write(os.urandom(40))
|
|
 |
7f5c89 |
- f.close()
|
|
 |
7f5c89 |
+ with open(options.serial_file) as f:
|
|
 |
7f5c89 |
+ serial_number = int(f.readline(), 16)
|
|
 |
7f5c89 |
+ return serial_number
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def run_cmd(cmd, input=None):
|
|
 |
7f5c89 |
- logging.debug("running command: %s", cmd)
|
|
 |
7f5c89 |
+def init_noise_file(options):
|
|
 |
7f5c89 |
+ '''Generate a noise file to be used when creating a key
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- if input is None:
|
|
 |
7f5c89 |
- stdin = None
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- stdin = subprocess.PIPE
|
|
 |
7f5c89 |
+ We create a temporary file on first use and continue to use
|
|
 |
7f5c89 |
+ the same temporary file for the duration of this process.
|
|
 |
7f5c89 |
+ Each time this function is called it writes new random data
|
|
 |
7f5c89 |
+ into the file.
|
|
 |
7f5c89 |
+ '''
|
|
 |
7f5c89 |
+ random_data = os.urandom(40)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
 |
7f5c89 |
- stdout, stderr = p.communicate(input)
|
|
 |
7f5c89 |
- status = p.returncode
|
|
 |
7f5c89 |
- if config['verbose']:
|
|
 |
7f5c89 |
- logging.debug("cmd status = %s", status)
|
|
 |
7f5c89 |
- logging.debug("cmd stdout = %s", stdout)
|
|
 |
7f5c89 |
- logging.debug("cmd stderr = %s", stderr)
|
|
 |
7f5c89 |
- return status, stdout, stderr
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-def run_cmd_with_prompts(cmd, prompts):
|
|
 |
7f5c89 |
- logging.debug('running command: %s', cmd)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- argv = shlex.split(cmd)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- pid, master_fd = pty.fork()
|
|
 |
7f5c89 |
- if pid == 0:
|
|
 |
7f5c89 |
- os.execlp(argv[0], *argv)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- time.sleep(0.1) # FIXME: why is this necessary?
|
|
 |
7f5c89 |
- output = ''
|
|
 |
7f5c89 |
- search_position = 0
|
|
 |
7f5c89 |
- cur_prompt = 0
|
|
 |
7f5c89 |
- if cur_prompt < len(prompts):
|
|
 |
7f5c89 |
- prompt_re = re.compile(prompts[cur_prompt][0])
|
|
 |
7f5c89 |
- response = prompts[cur_prompt][1]
|
|
 |
7f5c89 |
- cur_prompt += 1
|
|
 |
7f5c89 |
+ if options.noise_filename is None:
|
|
 |
7f5c89 |
+ fd, options.noise_filename = tempfile.mkstemp()
|
|
 |
7f5c89 |
+ os.write(fd, random_data)
|
|
 |
7f5c89 |
+ os.close(fd)
|
|
 |
7f5c89 |
else:
|
|
 |
7f5c89 |
- prompt_re = None
|
|
 |
7f5c89 |
- response = None
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- while True:
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- new_data = os.read(master_fd, 1024)
|
|
 |
7f5c89 |
- except OSError, e:
|
|
 |
7f5c89 |
- if e.errno == errno.EIO: # process exited
|
|
 |
7f5c89 |
- break
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- raise
|
|
 |
7f5c89 |
- if len(new_data) == 0:
|
|
 |
7f5c89 |
- break # EOF
|
|
 |
7f5c89 |
- output += new_data
|
|
 |
7f5c89 |
- logging.debug('output="%s"', output[search_position:]);
|
|
 |
7f5c89 |
- if prompt_re is not None:
|
|
 |
7f5c89 |
- logging.debug('search pattern = "%s"', prompt_re.pattern)
|
|
 |
7f5c89 |
- match = prompt_re.search(output, search_position)
|
|
 |
7f5c89 |
- if match:
|
|
 |
7f5c89 |
- search_position = match.end()
|
|
 |
7f5c89 |
- parsed = output[match.start() : match.end()]
|
|
 |
7f5c89 |
- logging.debug('found prompt: "%s"', parsed)
|
|
 |
7f5c89 |
- logging.debug('writing response: "%s"', response)
|
|
 |
7f5c89 |
- os.write(master_fd, response)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- if cur_prompt < len(prompts):
|
|
 |
7f5c89 |
- prompt_re = re.compile(prompts[cur_prompt][0])
|
|
 |
7f5c89 |
- response = prompts[cur_prompt][1]
|
|
 |
7f5c89 |
- cur_prompt += 1
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- prompt_re = None
|
|
 |
7f5c89 |
- response = None
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- exit_value = os.waitpid(pid, 0)[1]
|
|
 |
7f5c89 |
- exit_signal = exit_value & 0xFF
|
|
 |
7f5c89 |
- exit_code = exit_value >> 8
|
|
 |
7f5c89 |
- #logging.debug('output="%s"' % output)
|
|
 |
7f5c89 |
- logging.debug('cmd signal=%s, exit_code=%s' % (exit_signal, exit_code))
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- return exit_code, output
|
|
 |
7f5c89 |
+ with open(options.noise_filename, 'w') as f:
|
|
 |
7f5c89 |
+ f.write(random_data)
|
|
 |
7f5c89 |
+ return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+def create_passwd_file(options):
|
|
 |
7f5c89 |
+ fd, options.passwd_filename = tempfile.mkstemp()
|
|
 |
7f5c89 |
+ os.write(fd, options.db_passwd)
|
|
 |
7f5c89 |
+ os.close(fd)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def setup_certs():
|
|
 |
7f5c89 |
- print 'setting up certs ...'
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- if os.path.exists(config['dbdir']):
|
|
 |
7f5c89 |
- shutil.rmtree(config['dbdir'])
|
|
 |
7f5c89 |
- os.makedirs(config['dbdir'])
|
|
 |
7f5c89 |
+def db_has_cert(options, nickname):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-d', options.db_name,
|
|
 |
7f5c89 |
+ '-L',
|
|
 |
7f5c89 |
+ '-n', nickname]
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
+ run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ except CmdError as e:
|
|
 |
7f5c89 |
+ if e.returncode == 255 and 'not found' in e.stderr:
|
|
 |
7f5c89 |
+ return False
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ raise
|
|
 |
7f5c89 |
+ return True
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def format_cert(options, nickname):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-L', # OPERATION: list
|
|
 |
7f5c89 |
+ '-d', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-f', options.passwd_filename, # database password in file
|
|
 |
7f5c89 |
+ '-n', nickname, # nickname of cert to list
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- create_noise_file()
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 1. Create the database
|
|
 |
7f5c89 |
- cmd = 'certutil -N -d %(dbdir)s' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter new password:\s*', config['db_passwd'] + '\n'),
|
|
 |
7f5c89 |
- ('Re-enter password:\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 2. Create a root CA certificate
|
|
 |
7f5c89 |
- config['serial_number'] = next_serial()
|
|
 |
7f5c89 |
- cmd = 'certutil -S -d %(dbdir)s -z %(noise_file)s -s "%(ca_subject)s" -n "%(ca_nickname)s" -x -t "CTu,C,C" -m %(serial_number)d' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 3. Create a server certificate and sign it.
|
|
 |
7f5c89 |
- config['serial_number'] = next_serial()
|
|
 |
7f5c89 |
- cmd = 'certutil -S -d %(dbdir)s -z %(noise_file)s -c %(ca_nickname)s -s "%(server_subject)s" -n "%(server_nickname)s" -t "u,u,u" -m %(serial_number)d' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 4. Create a client certificate and sign it.
|
|
 |
7f5c89 |
- config['serial_number'] = next_serial()
|
|
 |
7f5c89 |
- cmd = 'certutil -S -d %(dbdir)s -z %(noise_file)s -c %(ca_nickname)s -s "%(client_subject)s" -n "%(client_nickname)s" -t "u,u,u" -m %(serial_number)d' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 5. Import public root CA's
|
|
 |
7f5c89 |
- cmd = 'modutil -dbdir %(dbdir)s -add ca_certs -libfile libnssckbi.so' % config
|
|
 |
7f5c89 |
- exit_code, stdout, stderr = run_cmd(cmd)
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 6. Create a sub CA certificate
|
|
 |
7f5c89 |
- config['serial_number'] = next_serial()
|
|
 |
7f5c89 |
- config['subca_subject'] = 'CN=subca'
|
|
 |
7f5c89 |
- config['subca_nickname'] = 'subca'
|
|
 |
7f5c89 |
- cmd = 'certutil -S -d %(dbdir)s -z %(noise_file)s -c %(ca_nickname)s -s "%(subca_subject)s" -n "%(subca_nickname)s" -t "CTu,C,C" -m %(serial_number)d' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- # 7. Create a server certificate and sign it with the subca.
|
|
 |
7f5c89 |
- config['serial_number'] = next_serial()
|
|
 |
7f5c89 |
- config['server_subject'] = config['server_subject'] + "_" + config['subca_nickname']
|
|
 |
7f5c89 |
- config['server_nickname'] = config['server_nickname'] + "_" + config['subca_nickname']
|
|
 |
7f5c89 |
- cmd = 'certutil -S -d %(dbdir)s -z %(noise_file)s -c %(subca_nickname)s -s "%(server_subject)s" -n "%(server_nickname)s" -t "u,u,u" -m %(serial_number)d' % config
|
|
 |
7f5c89 |
- exit_code, output = run_cmd_with_prompts(cmd,
|
|
 |
7f5c89 |
- [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
|
|
 |
7f5c89 |
- if exit_code != 0:
|
|
 |
7f5c89 |
- raise CmdError(cmd, exit_code, output)
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- finally:
|
|
 |
7f5c89 |
- if os.path.exists(config['noise_file']):
|
|
 |
7f5c89 |
- os.remove(config['noise_file'])
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- logging.info('certifcate database password="%(db_passwd)s"', config)
|
|
 |
7f5c89 |
- logging.info('CA nickname="%(ca_nickname)s", CA subject="%(ca_subject)s"', config)
|
|
 |
7f5c89 |
- logging.info('server nickname="%(server_nickname)s", server subject="%(server_subject)s"', config)
|
|
 |
7f5c89 |
- logging.info('client nickname="%(client_nickname)s", client subject="%(client_subject)s"', config)
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ return stdout
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-class Usage(Exception):
|
|
 |
7f5c89 |
- def __init__(self, msg):
|
|
 |
7f5c89 |
- self.msg = msg
|
|
 |
7f5c89 |
+def create_database(options):
|
|
 |
7f5c89 |
+ if os.path.exists(options.db_dir) and not os.path.isdir(options.db_dir):
|
|
 |
7f5c89 |
+ raise ValueError('db_dir "%s" exists but is not a directory' % options.db_dir)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Create resources
|
|
 |
7f5c89 |
+ create_passwd_file(options)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ if options.clean:
|
|
 |
7f5c89 |
+ logging.info('Creating clean database directory: "%s"', options.db_dir)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ if os.path.exists(options.db_dir):
|
|
 |
7f5c89 |
+ shutil.rmtree(options.db_dir)
|
|
 |
7f5c89 |
+ os.makedirs(options.db_dir)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-N', # OPERATION: create database
|
|
 |
7f5c89 |
+ '-d', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-f', options.passwd_filename, # database password in file
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def usage():
|
|
 |
7f5c89 |
- '''
|
|
 |
7f5c89 |
- Print command help.
|
|
 |
7f5c89 |
- '''
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ logging.info('Using existing database directory: "%s"', options.db_dir)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def create_ca_cert(options):
|
|
 |
7f5c89 |
+ serial_number = read_serial(options)
|
|
 |
7f5c89 |
+ init_noise_file(options)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ logging.info('creating ca cert: subject="%s", nickname="%s"',
|
|
 |
7f5c89 |
+ options.ca_subject, options.ca_nickname)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-S', # OPERATION: create signed cert
|
|
 |
7f5c89 |
+ '-x', # self-sign the cert
|
|
 |
7f5c89 |
+ '-d', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-f', options.passwd_filename, # database password in file
|
|
 |
7f5c89 |
+ '-n', options.ca_nickname, # nickname of cert being created
|
|
 |
7f5c89 |
+ '-s', options.ca_subject, # subject of cert being created
|
|
 |
7f5c89 |
+ '-g', str(options.key_size), # keysize
|
|
 |
7f5c89 |
+ '-t', 'CT,,CT', # trust
|
|
 |
7f5c89 |
+ '-1', # add key usage extension
|
|
 |
7f5c89 |
+ '-2', # add basic contraints extension
|
|
 |
7f5c89 |
+ '-5', # add certificate type extension
|
|
 |
7f5c89 |
+ '-m', str(serial_number), # cert serial number
|
|
 |
7f5c89 |
+ '-v', str(options.valid_months), # validity in months
|
|
 |
7f5c89 |
+ '-z', options.noise_filename, # noise file random seed
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Provide input for extension creation prompting
|
|
 |
7f5c89 |
+ input = ''
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # >> Key Usage extension <<
|
|
 |
7f5c89 |
+ # 0 - Digital Signature
|
|
 |
7f5c89 |
+ # 1 - Non-repudiation
|
|
 |
7f5c89 |
+ # 2 - Key encipherment
|
|
 |
7f5c89 |
+ # 3 - Data encipherment
|
|
 |
7f5c89 |
+ # 4 - Key agreement
|
|
 |
7f5c89 |
+ # 5 - Cert signing key
|
|
 |
7f5c89 |
+ # 6 - CRL signing key
|
|
 |
7f5c89 |
+ # Other to finish
|
|
 |
7f5c89 |
+ input += '0\n1\n5\n100\n'
|
|
 |
7f5c89 |
+ # Is this a critical extension [y/N]?
|
|
 |
7f5c89 |
+ input += 'y\n'
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # >> Basic Constraints extension <<
|
|
 |
7f5c89 |
+ # Is this a CA certificate [y/N]?
|
|
 |
7f5c89 |
+ input += 'y\n'
|
|
 |
7f5c89 |
+ # Enter the path length constraint, enter to skip [<0 for unlimited path]: > 2
|
|
 |
7f5c89 |
+ input += '%d\n' % options.ca_path_len
|
|
 |
7f5c89 |
+ # Is this a critical extension [y/N]?
|
|
 |
7f5c89 |
+ input += 'y\n'
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # >> NS Cert Type extension <<
|
|
 |
7f5c89 |
+ # 0 - SSL Client
|
|
 |
7f5c89 |
+ # 1 - SSL Server
|
|
 |
7f5c89 |
+ # 2 - S/MIME
|
|
 |
7f5c89 |
+ # 3 - Object Signing
|
|
 |
7f5c89 |
+ # 4 - Reserved for future use
|
|
 |
7f5c89 |
+ # 5 - SSL CA
|
|
 |
7f5c89 |
+ # 6 - S/MIME CA
|
|
 |
7f5c89 |
+ # 7 - Object Signing CA
|
|
 |
7f5c89 |
+ # Other to finish
|
|
 |
7f5c89 |
+ input += '5\n6\n7\n100\n'
|
|
 |
7f5c89 |
+ # Is this a critical extension [y/N]?
|
|
 |
7f5c89 |
+ input += 'n\n'
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args, input)
|
|
 |
7f5c89 |
+ write_serial(options, serial_number + 1)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ return options.ca_nickname
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def create_server_cert(options):
|
|
 |
7f5c89 |
+ serial_number = read_serial(options)
|
|
 |
7f5c89 |
+ init_noise_file(options)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ logging.info('creating server cert: subject="%s", nickname="%s"',
|
|
 |
7f5c89 |
+ options.server_subject, options.server_nickname)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-S', # OPERATION: create signed cert
|
|
 |
7f5c89 |
+ '-d', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-f', options.passwd_filename, # database password in file
|
|
 |
7f5c89 |
+ '-c', options.ca_nickname, # nickname of CA used to sign this cert
|
|
 |
7f5c89 |
+ '-n', options.server_nickname, # nickname of cert being created
|
|
 |
7f5c89 |
+ '-s', options.server_subject, # subject of cert being created
|
|
 |
7f5c89 |
+ '-g', str(options.key_size), # keysize
|
|
 |
7f5c89 |
+ '-t', 'u,u,u', # trust
|
|
 |
7f5c89 |
+ '-5', # add certificate type extensionn
|
|
 |
7f5c89 |
+ '-m', str(serial_number), # cert serial number
|
|
 |
7f5c89 |
+ '-v', str(options.valid_months), # validity in months
|
|
 |
7f5c89 |
+ '-z', options.noise_filename, # noise file random seed
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Provide input for extension creation prompting
|
|
 |
7f5c89 |
+ input = ''
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # >> NS Cert Type extension <<
|
|
 |
7f5c89 |
+ # 0 - SSL Client
|
|
 |
7f5c89 |
+ # 1 - SSL Server
|
|
 |
7f5c89 |
+ # 2 - S/MIME
|
|
 |
7f5c89 |
+ # 3 - Object Signing
|
|
 |
7f5c89 |
+ # 4 - Reserved for future use
|
|
 |
7f5c89 |
+ # 5 - SSL CA
|
|
 |
7f5c89 |
+ # 6 - S/MIME CA
|
|
 |
7f5c89 |
+ # 7 - Object Signing CA
|
|
 |
7f5c89 |
+ # Other to finish
|
|
 |
7f5c89 |
+ input += '1\n100\n'
|
|
 |
7f5c89 |
+ # Is this a critical extension [y/N]?
|
|
 |
7f5c89 |
+ input += 'n\n'
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args, input)
|
|
 |
7f5c89 |
+ write_serial(options, serial_number + 1)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ return options.server_nickname
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def create_client_cert(options):
|
|
 |
7f5c89 |
+ serial_number = read_serial(options)
|
|
 |
7f5c89 |
+ init_noise_file(options)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ logging.info('creating client cert: subject="%s", nickname="%s"',
|
|
 |
7f5c89 |
+ options.client_subject, options.client_nickname)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-S', # OPERATION: create signed cert
|
|
 |
7f5c89 |
+ '-d', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-f', options.passwd_filename, # database password in file
|
|
 |
7f5c89 |
+ '-c', options.ca_nickname, # nickname of CA used to sign this cert
|
|
 |
7f5c89 |
+ '-n', options.client_nickname, # nickname of cert being created
|
|
 |
7f5c89 |
+ '-s', options.client_subject, # subject of cert being created
|
|
 |
7f5c89 |
+ '-g', str(options.key_size), # keysize
|
|
 |
7f5c89 |
+ '-t', 'u,u,u', # trust
|
|
 |
7f5c89 |
+ '-5', # add certificate type extensionn
|
|
 |
7f5c89 |
+ '-m', str(serial_number), # cert serial number
|
|
 |
7f5c89 |
+ '-v', str(options.valid_months), # validity in months
|
|
 |
7f5c89 |
+ '-z', options.noise_filename, # noise file random seed
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Provide input for extension creation prompting
|
|
 |
7f5c89 |
+ input = ''
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # >> NS Cert Type extension <<
|
|
 |
7f5c89 |
+ # 0 - SSL Client
|
|
 |
7f5c89 |
+ # 1 - SSL Server
|
|
 |
7f5c89 |
+ # 2 - S/MIME
|
|
 |
7f5c89 |
+ # 3 - Object Signing
|
|
 |
7f5c89 |
+ # 4 - Reserved for future use
|
|
 |
7f5c89 |
+ # 5 - SSL CA
|
|
 |
7f5c89 |
+ # 6 - S/MIME CA
|
|
 |
7f5c89 |
+ # 7 - Object Signing CA
|
|
 |
7f5c89 |
+ # Other to finish
|
|
 |
7f5c89 |
+ input += '0\n100\n'
|
|
 |
7f5c89 |
+ # Is this a critical extension [y/N]?
|
|
 |
7f5c89 |
+ input += 'n\n'
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args, input)
|
|
 |
7f5c89 |
+ write_serial(options, serial_number + 1)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ return options.client_nickname
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def add_trusted_certs(options):
|
|
 |
7f5c89 |
+ name = 'ca_certs'
|
|
 |
7f5c89 |
+ module = 'libnssckbi.so'
|
|
 |
7f5c89 |
+ logging.info('adding system trusted certs: name="%s" module="%s"',
|
|
 |
7f5c89 |
+ name, module)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/modutil',
|
|
 |
7f5c89 |
+ '-dbdir', options.db_name, # NSS database
|
|
 |
7f5c89 |
+ '-add', name, # module name
|
|
 |
7f5c89 |
+ '-libfile', module, # module
|
|
 |
7f5c89 |
+ ]
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- return '''\
|
|
 |
7f5c89 |
--h --help print help
|
|
 |
7f5c89 |
--l --log-level level set the logging level, may be one of:
|
|
 |
7f5c89 |
- debug, info, warn, error, critical
|
|
 |
7f5c89 |
--L --logfile filename log to this file, empty string disables logging to a file
|
|
 |
7f5c89 |
--v --verbose be chatty
|
|
 |
7f5c89 |
--D --debug show run information
|
|
 |
7f5c89 |
--w --password set the certificate database password
|
|
 |
7f5c89 |
--d --dbdir set the datbase directory
|
|
 |
7f5c89 |
--s --server-subject set the server's subject
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-Examples:
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-%(prog_name)s -m 10
|
|
 |
7f5c89 |
-''' % {'prog_name' : prog_name,
|
|
 |
7f5c89 |
- }
|
|
 |
7f5c89 |
+ run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ return name
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def main(argv=None):
|
|
 |
7f5c89 |
- if argv is None:
|
|
 |
7f5c89 |
- argv = sys.argv
|
|
 |
7f5c89 |
+def setup_certs(args):
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- try:
|
|
 |
7f5c89 |
- opts, args = getopt.getopt(argv[1:], 'hl:L:vDw:d:s:',
|
|
 |
7f5c89 |
- ['help', 'logfile=', 'verbose', 'debug',
|
|
 |
7f5c89 |
- 'password', 'dbdir', 'server-subject'])
|
|
 |
7f5c89 |
- except getopt.GetoptError, e:
|
|
 |
7f5c89 |
- raise Usage(e)
|
|
 |
7f5c89 |
- return 2
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- for o, a in opts:
|
|
 |
7f5c89 |
- if o in ('-h', '--help'):
|
|
 |
7f5c89 |
- print >>sys.stdout, usage()
|
|
 |
7f5c89 |
- return 0
|
|
 |
7f5c89 |
- elif o in ('-L', '--logfile'):
|
|
 |
7f5c89 |
- if not a:
|
|
 |
7f5c89 |
- config['logfile'] = None
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- config['logfile'] = a
|
|
 |
7f5c89 |
- elif o in ('-l', '--log-level'):
|
|
 |
7f5c89 |
- if a.upper() in logging._levelNames:
|
|
 |
7f5c89 |
- config['log_level'] = logging._levelNames[a.upper()]
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- print >>sys.stderr, "ERROR: unknown log-level '%s'" % a
|
|
 |
7f5c89 |
- elif o in ('-v', '--verbose'):
|
|
 |
7f5c89 |
- config['verbose'] = True
|
|
 |
7f5c89 |
- elif o in ('-D', '--debug'):
|
|
 |
7f5c89 |
- config['debug'] = True
|
|
 |
7f5c89 |
- elif o in ('-w', '--password'):
|
|
 |
7f5c89 |
- config['db_passwd'] = a
|
|
 |
7f5c89 |
- elif o in ('-d', '--dbdir'):
|
|
 |
7f5c89 |
- config['dbdir'] = a
|
|
 |
7f5c89 |
- elif o in ('-s', '--server-subject'):
|
|
 |
7f5c89 |
- config['server_subject'] = 'CN=%s' % a
|
|
 |
7f5c89 |
- else:
|
|
 |
7f5c89 |
- raise Usage("command argument '%s' not handled, internal error" % o)
|
|
 |
7f5c89 |
- except Usage, e:
|
|
 |
7f5c89 |
- print >>sys.stderr, e.msg
|
|
 |
7f5c89 |
- print >>sys.stderr, "for help use --help"
|
|
 |
7f5c89 |
- return 2
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- if config['verbose']:
|
|
 |
7f5c89 |
- config['log_level'] = logging.INFO
|
|
 |
7f5c89 |
- if config['debug']:
|
|
 |
7f5c89 |
- config['log_level'] = logging.DEBUG
|
|
 |
7f5c89 |
+ # --- cmd ---
|
|
 |
7f5c89 |
+ parser = argparse.ArgumentParser(description='create certs for testing',
|
|
 |
7f5c89 |
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--verbose', action='store_true',
|
|
 |
7f5c89 |
+ help='provide info level messages')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--debug', action='store_true',
|
|
 |
7f5c89 |
+ help='provide debug level messages')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--quiet', action='store_true',
|
|
 |
7f5c89 |
+ help='do not display any messages')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--show-certs', action='store_true',
|
|
 |
7f5c89 |
+ help='show the certificate details')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--no-clean', action='store_false', dest='clean',
|
|
 |
7f5c89 |
+ help='do not remove existing db_dir')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--no-trusted-certs', dest='add_trusted_certs', action='store_false',
|
|
 |
7f5c89 |
+ help='do not add trusted certs')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--hostname',
|
|
 |
7f5c89 |
+ help='hostname used in cert subjects')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--db-type',
|
|
 |
7f5c89 |
+ choices=['sql', ''],
|
|
 |
7f5c89 |
+ help='NSS database type')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--db-dir',
|
|
 |
7f5c89 |
+ help='NSS database directory')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--db-passwd',
|
|
 |
7f5c89 |
+ help='NSS database password')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--ca-subject',
|
|
 |
7f5c89 |
+ help='CA certificate subject')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--ca-nickname',
|
|
 |
7f5c89 |
+ help='CA certificate nickname')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--server-subject',
|
|
 |
7f5c89 |
+ help='server certificate subject')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--server-nickname',
|
|
 |
7f5c89 |
+ help='server certificate nickname')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--client-username',
|
|
 |
7f5c89 |
+ help='client user name, used in client cert subject')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--client-subject',
|
|
 |
7f5c89 |
+ help='client certificate subject')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--client-nickname',
|
|
 |
7f5c89 |
+ help='client certificate nickname')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--serial-number', type=int,
|
|
 |
7f5c89 |
+ help='starting serial number for certificates')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.add_argument('--valid-months', dest='valid_months', type=int,
|
|
 |
7f5c89 |
+ help='validity period in months')
|
|
 |
7f5c89 |
+ parser.add_argument('--path-len', dest='ca_path_len', type=int,
|
|
 |
7f5c89 |
+ help='basic constraints path length')
|
|
 |
7f5c89 |
+ parser.add_argument('--key-type', dest='key_type',
|
|
 |
7f5c89 |
+ help='key type, either rsa or dsa')
|
|
 |
7f5c89 |
+ parser.add_argument('--key-size', dest='key_size',
|
|
 |
7f5c89 |
+ help='number of bits in key (must be multiple of 8)')
|
|
 |
7f5c89 |
+ parser.add_argument('--serial-file', dest='serial_file',
|
|
 |
7f5c89 |
+ help='name of file used to track next serial number')
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ parser.set_defaults(verbose = False,
|
|
 |
7f5c89 |
+ debug = False,
|
|
 |
7f5c89 |
+ quiet = False,
|
|
 |
7f5c89 |
+ show_certs = False,
|
|
 |
7f5c89 |
+ clean = True,
|
|
 |
7f5c89 |
+ add_trusted_certs = True,
|
|
 |
7f5c89 |
+ hostname = os.uname()[1],
|
|
 |
7f5c89 |
+ db_type = 'sql',
|
|
 |
7f5c89 |
+ db_dir = 'pki',
|
|
 |
7f5c89 |
+ db_passwd = 'db_passwd',
|
|
 |
7f5c89 |
+ ca_subject = 'CN=Test CA',
|
|
 |
7f5c89 |
+ ca_nickname = 'test_ca',
|
|
 |
7f5c89 |
+ server_subject = 'CN=${hostname}',
|
|
 |
7f5c89 |
+ server_nickname = 'test_server',
|
|
 |
7f5c89 |
+ client_username = 'test_user',
|
|
 |
7f5c89 |
+ client_subject = 'CN=${client_username}',
|
|
 |
7f5c89 |
+ client_nickname = '${client_username}',
|
|
 |
7f5c89 |
+ serial_number = 1,
|
|
 |
7f5c89 |
+ key_type = 'rsa',
|
|
 |
7f5c89 |
+ key_size = 1024,
|
|
 |
7f5c89 |
+ valid_months = 12,
|
|
 |
7f5c89 |
+ ca_path_len = 2,
|
|
 |
7f5c89 |
+ serial_file = '${db_dir}/serial',
|
|
 |
7f5c89 |
+ )
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ options = parser.parse_args(args)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Do substitutions on option values.
|
|
 |
7f5c89 |
+ # This is ugly because argparse does not expose an API which permits iterating over
|
|
 |
7f5c89 |
+ # the contents of options nor a way to get the options as a dict, ugh :-(
|
|
 |
7f5c89 |
+ # So we access options.__dict__ directly.
|
|
 |
7f5c89 |
+ for key in options.__dict__.keys():
|
|
 |
7f5c89 |
+ # Assume options never begin with underscore
|
|
 |
7f5c89 |
+ if key.startswith('_'):
|
|
 |
7f5c89 |
+ continue
|
|
 |
7f5c89 |
+ value = getattr(options, key)
|
|
 |
7f5c89 |
+ # Can't substitue on non-string values
|
|
 |
7f5c89 |
+ if not isinstance(value, basestring):
|
|
 |
7f5c89 |
+ continue
|
|
 |
7f5c89 |
+ # Don't bother trying to substitute if $ substitution character isn't present
|
|
 |
7f5c89 |
+ if '$' not in value:
|
|
 |
7f5c89 |
+ continue
|
|
 |
7f5c89 |
+ setattr(options, key, Template(value).substitute(options.__dict__))
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Set up logging
|
|
 |
7f5c89 |
+ log_level = logging.INFO
|
|
 |
7f5c89 |
+ if options.quiet:
|
|
 |
7f5c89 |
+ log_level = logging.ERROR
|
|
 |
7f5c89 |
+ if options.verbose:
|
|
 |
7f5c89 |
+ log_level = logging.INFO
|
|
 |
7f5c89 |
+ if options.debug:
|
|
 |
7f5c89 |
+ log_level = logging.DEBUG
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Initialize logging
|
|
 |
7f5c89 |
- logging.basicConfig(level=config['log_level'],
|
|
 |
7f5c89 |
- format='%(asctime)s %(levelname)-8s %(message)s',
|
|
 |
7f5c89 |
- datefmt='%m-%d %H:%M',
|
|
 |
7f5c89 |
- filename=config['logfile'],
|
|
 |
7f5c89 |
- filemode='a')
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- if config['interactive']:
|
|
 |
7f5c89 |
- # Create a seperate logger for the console
|
|
 |
7f5c89 |
- console_logger = logging.StreamHandler()
|
|
 |
7f5c89 |
- console_logger.setLevel(config['log_level'])
|
|
 |
7f5c89 |
- # set a format which is simpler for console use
|
|
 |
7f5c89 |
- formatter = logging.Formatter('%(message)s')
|
|
 |
7f5c89 |
- console_logger.setFormatter(formatter)
|
|
 |
7f5c89 |
- # add the handler to the root logger
|
|
 |
7f5c89 |
- logging.getLogger('').addHandler(console_logger)
|
|
 |
7f5c89 |
+ logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s')
|
|
 |
7f5c89 |
+ logger = logging.getLogger()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Synthesize some useful options derived from specified options
|
|
 |
7f5c89 |
+ if options.db_type == '':
|
|
 |
7f5c89 |
+ options.db_name = options.db_dir
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ options.db_name = '%s:%s' % (options.db_type, options.db_dir)
|
|
 |
7f5c89 |
+ options.passwd_filename = None
|
|
 |
7f5c89 |
+ options.noise_filename = None
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Set function to clean up on exit, bind fuction with options
|
|
 |
7f5c89 |
+ def exit_handler_with_options():
|
|
 |
7f5c89 |
+ exit_handler(options)
|
|
 |
7f5c89 |
+ atexit.register(exit_handler_with_options)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ cert_nicknames = []
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
- setup_certs()
|
|
 |
7f5c89 |
- except Exception, e:
|
|
 |
7f5c89 |
- logging.error(traceback.format_exc())
|
|
 |
7f5c89 |
- logging.error(str(e))
|
|
 |
7f5c89 |
+ create_database(options)
|
|
 |
7f5c89 |
+ cert_nicknames.append(create_ca_cert(options))
|
|
 |
7f5c89 |
+ cert_nicknames.append(create_server_cert(options))
|
|
 |
7f5c89 |
+ cert_nicknames.append(create_client_cert(options))
|
|
 |
7f5c89 |
+ if options.add_trusted_certs:
|
|
 |
7f5c89 |
+ add_trusted_certs(options)
|
|
 |
7f5c89 |
+ except CmdError as e:
|
|
 |
7f5c89 |
+ logging.error(e.message)
|
|
 |
7f5c89 |
+ logging.error(e.stderr)
|
|
 |
7f5c89 |
return 1
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+ if options.show_certs:
|
|
 |
7f5c89 |
+ if logger.getEffectiveLevel() > logging.INFO:
|
|
 |
7f5c89 |
+ logger.setLevel(logging.INFO)
|
|
 |
7f5c89 |
+ for nickname in cert_nicknames:
|
|
 |
7f5c89 |
+ logging.info('Certificate nickname "%s"\n%s',
|
|
 |
7f5c89 |
+ nickname, format_cert(options, nickname))
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ logging.info('---------- Summary ----------')
|
|
 |
7f5c89 |
+ logging.info('NSS database name="%s", password="%s"',
|
|
 |
7f5c89 |
+ options.db_name, options.db_passwd)
|
|
 |
7f5c89 |
+ logging.info('CA nickname="%s", CA subject="%s"',
|
|
 |
7f5c89 |
+ options.ca_nickname, options.ca_subject)
|
|
 |
7f5c89 |
+ logging.info('server nickname="%s", server subject="%s"',
|
|
 |
7f5c89 |
+ options.server_nickname, options.server_subject)
|
|
 |
7f5c89 |
+ logging.info('client nickname="%s", client subject="%s"',
|
|
 |
7f5c89 |
+ options.client_nickname, options.client_subject)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
return 0
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+def main():
|
|
 |
7f5c89 |
+ return setup_certs(None)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
if __name__ == '__main__':
|
|
 |
7f5c89 |
sys.exit(main())
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/test_client_server.py python-nss-0.14.1/test/test_client_server.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/test_client_server.py 2013-04-30 13:00:23.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/test_client_server.py 2013-10-08 09:35:53.000000000 -0400
|
|
 |
7f5c89 |
@@ -25,13 +25,12 @@
|
|
 |
7f5c89 |
password = 'db_passwd'
|
|
 |
7f5c89 |
use_ssl = True
|
|
 |
7f5c89 |
client_cert_action = NO_CLIENT_CERT
|
|
 |
7f5c89 |
-certdir = os.path.join(os.path.dirname(sys.argv[0]), 'pki')
|
|
 |
7f5c89 |
+db_name = 'sql:pki'
|
|
 |
7f5c89 |
hostname = os.uname()[1]
|
|
 |
7f5c89 |
server_nickname = 'test_server'
|
|
 |
7f5c89 |
client_nickname = 'test_user'
|
|
 |
7f5c89 |
port = 1234
|
|
 |
7f5c89 |
timeout_secs = 10
|
|
 |
7f5c89 |
-family = io.PR_AF_INET
|
|
 |
7f5c89 |
sleep_time = 5
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -142,7 +141,6 @@
|
|
 |
7f5c89 |
if info: print "client: using SSL"
|
|
 |
7f5c89 |
ssl.set_domestic_policy()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- valid_addr = False
|
|
 |
7f5c89 |
# Get the IP Address of our server
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
addr_info = io.AddrInfo(hostname)
|
|
 |
7f5c89 |
@@ -151,8 +149,6 @@
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
for net_addr in addr_info:
|
|
 |
7f5c89 |
- if family != io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
- if net_addr.family != family: continue
|
|
 |
7f5c89 |
net_addr.port = port
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if use_ssl:
|
|
 |
7f5c89 |
@@ -180,26 +176,21 @@
|
|
 |
7f5c89 |
if verbose: print "client trying connection to: %s" % (net_addr)
|
|
 |
7f5c89 |
sock.connect(net_addr, timeout=io.seconds_to_interval(timeout_secs))
|
|
 |
7f5c89 |
if verbose: print "client connected to: %s" % (net_addr)
|
|
 |
7f5c89 |
- valid_addr = True
|
|
 |
7f5c89 |
break
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
sock.close()
|
|
 |
7f5c89 |
print >>sys.stderr, "client: connection to: %s failed (%s)" % (net_addr, e)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
- if not valid_addr:
|
|
 |
7f5c89 |
- print >>sys.stderr, "Could not establish valid address for \"%s\" in family %s" % \
|
|
 |
7f5c89 |
- (hostname, io.addr_family_name(family))
|
|
 |
7f5c89 |
- return
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
# Talk to the server
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
if info: print "client: sending \"%s\"" % (request)
|
|
 |
7f5c89 |
- sock.send(request)
|
|
 |
7f5c89 |
- buf = sock.recv(1024)
|
|
 |
7f5c89 |
+ sock.send(request + '\n') # newline is protocol record separator
|
|
 |
7f5c89 |
+ buf = sock.readline()
|
|
 |
7f5c89 |
if not buf:
|
|
 |
7f5c89 |
print >>sys.stderr, "client: lost connection"
|
|
 |
7f5c89 |
sock.close()
|
|
 |
7f5c89 |
return
|
|
 |
7f5c89 |
+ buf = buf.rstrip() # remove newline record separator
|
|
 |
7f5c89 |
if info: print "client: received \"%s\"" % (buf)
|
|
 |
7f5c89 |
except Exception, e:
|
|
 |
7f5c89 |
print >>sys.stderr, "client: %s" % e
|
|
 |
7f5c89 |
@@ -228,15 +219,11 @@
|
|
 |
7f5c89 |
# -----------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def server():
|
|
 |
7f5c89 |
- global family
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
if verbose: print "starting server:"
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
# Initialize
|
|
 |
7f5c89 |
# Setup an IP Address to listen on any of our interfaces
|
|
 |
7f5c89 |
- if family == io.PR_AF_UNSPEC:
|
|
 |
7f5c89 |
- family = io.PR_AF_INET
|
|
 |
7f5c89 |
- net_addr = io.NetworkAddress(io.PR_IpAddrAny, port, family)
|
|
 |
7f5c89 |
+ net_addr = io.NetworkAddress(io.PR_IpAddrAny, port)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if use_ssl:
|
|
 |
7f5c89 |
if info: print "server: using SSL"
|
|
 |
7f5c89 |
@@ -290,15 +277,16 @@
|
|
 |
7f5c89 |
while True:
|
|
 |
7f5c89 |
try:
|
|
 |
7f5c89 |
# Handle the client connection
|
|
 |
7f5c89 |
- buf = client_sock.recv(1024)
|
|
 |
7f5c89 |
+ buf = client_sock.readline() # newline is protocol record separator
|
|
 |
7f5c89 |
if not buf:
|
|
 |
7f5c89 |
print >>sys.stderr, "server: lost lost connection to %s" % (client_addr)
|
|
 |
7f5c89 |
break
|
|
 |
7f5c89 |
+ buf = buf.rstrip() # remove newline record separator
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if info: print "server: received \"%s\"" % (buf)
|
|
 |
7f5c89 |
- reply = "{%s}" % buf # echo
|
|
 |
7f5c89 |
+ reply = "{%s}" % buf # echo embedded inside braces
|
|
 |
7f5c89 |
if info: print "server: sending \"%s\"" % (reply)
|
|
 |
7f5c89 |
- client_sock.send(reply) # echo
|
|
 |
7f5c89 |
+ client_sock.send(reply + '\n') # send echo with record separator
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
time.sleep(sleep_time)
|
|
 |
7f5c89 |
client_sock.shutdown()
|
|
 |
7f5c89 |
@@ -320,7 +308,7 @@
|
|
 |
7f5c89 |
def run_server():
|
|
 |
7f5c89 |
pid = os.fork()
|
|
 |
7f5c89 |
if pid == 0:
|
|
 |
7f5c89 |
- nss.nss_init(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init(db_name)
|
|
 |
7f5c89 |
server()
|
|
 |
7f5c89 |
nss.nss_shutdown()
|
|
 |
7f5c89 |
time.sleep(sleep_time)
|
|
 |
7f5c89 |
@@ -348,7 +336,7 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def test_ssl(self):
|
|
 |
7f5c89 |
request = "foo"
|
|
 |
7f5c89 |
- nss.nss_init(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init(db_name)
|
|
 |
7f5c89 |
reply = client(request)
|
|
 |
7f5c89 |
nss.nss_shutdown()
|
|
 |
7f5c89 |
self.assertEqual("{%s}" % request, reply)
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/test_ocsp.py python-nss-0.14.1/test/test_ocsp.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/test_ocsp.py 2013-04-24 12:36:07.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/test_ocsp.py 2013-10-08 09:09:18.000000000 -0400
|
|
 |
7f5c89 |
@@ -7,7 +7,7 @@
|
|
 |
7f5c89 |
import nss.nss as nss
|
|
 |
7f5c89 |
from nss.error import NSPRError
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-certdir = 'pki'
|
|
 |
7f5c89 |
+db_name = 'sql:pki'
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
@@ -16,7 +16,7 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
class TestAPI(unittest.TestCase):
|
|
 |
7f5c89 |
def setUp(self):
|
|
 |
7f5c89 |
- nss.nss_init_read_write(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init_read_write(db_name)
|
|
 |
7f5c89 |
self.certdb = nss.get_default_certdb()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def tearDown(self):
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/test_pkcs12.py python-nss-0.14.1/test/test_pkcs12.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/test_pkcs12.py 2013-04-15 13:05:46.000000000 -0400
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/test_pkcs12.py 2013-10-17 10:29:09.000000000 -0400
|
|
 |
7f5c89 |
@@ -2,6 +2,7 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
import sys
|
|
 |
7f5c89 |
import os
|
|
 |
7f5c89 |
+import re
|
|
 |
7f5c89 |
import subprocess
|
|
 |
7f5c89 |
import shlex
|
|
 |
7f5c89 |
import unittest
|
|
 |
7f5c89 |
@@ -13,30 +14,55 @@
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
verbose = False
|
|
 |
7f5c89 |
-certdir = 'pki'
|
|
 |
7f5c89 |
+db_name = 'sql:pki'
|
|
 |
7f5c89 |
db_passwd = 'db_passwd'
|
|
 |
7f5c89 |
-pkcs12_file_password = 'pk12_passwd'
|
|
 |
7f5c89 |
+pk12_passwd = 'pk12_passwd'
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-read_nickname = 'test_user'
|
|
 |
7f5c89 |
-read_pkcs12_file = '%s.p12' % read_nickname
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
-write_export_file = False
|
|
 |
7f5c89 |
-export_nickname = 'test_server'
|
|
 |
7f5c89 |
+cert_nickname = 'test_user'
|
|
 |
7f5c89 |
+pk12_filename = '%s.p12' % cert_nickname
|
|
 |
7f5c89 |
+exported_pk12_filename = 'exported_%s' % pk12_filename
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-def run_cmd(cmd):
|
|
 |
7f5c89 |
- if verbose: print "running command: %s" % cmd
|
|
 |
7f5c89 |
-
|
|
 |
7f5c89 |
- args = shlex.split(cmd)
|
|
 |
7f5c89 |
- subprocess.check_call(args, stdout=subprocess.PIPE)
|
|
 |
7f5c89 |
+class CmdError(Exception):
|
|
 |
7f5c89 |
+ def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None):
|
|
 |
7f5c89 |
+ self.cmd_args = cmd_args
|
|
 |
7f5c89 |
+ self.returncode = returncode
|
|
 |
7f5c89 |
+ if message is None:
|
|
 |
7f5c89 |
+ self.message = 'Failed error=%s, ' % (returncode)
|
|
 |
7f5c89 |
+ if stderr:
|
|
 |
7f5c89 |
+ self.message += '"%s", ' % stderr
|
|
 |
7f5c89 |
+ self.message += 'args=%s' % (cmd_args)
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ self.message = message
|
|
 |
7f5c89 |
+ self.stdout = stdout
|
|
 |
7f5c89 |
+ self.stderr = stderr
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ def __str__(self):
|
|
 |
7f5c89 |
+ return self.message
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def run_cmd(cmd_args, input=None):
|
|
 |
7f5c89 |
+ try:
|
|
 |
7f5c89 |
+ p = subprocess.Popen(cmd_args,
|
|
 |
7f5c89 |
+ stdin=subprocess.PIPE,
|
|
 |
7f5c89 |
+ stdout=subprocess.PIPE,
|
|
 |
7f5c89 |
+ stderr=subprocess.PIPE)
|
|
 |
7f5c89 |
+ stdout, stderr = p.communicate(input)
|
|
 |
7f5c89 |
+ returncode = p.returncode
|
|
 |
7f5c89 |
+ if returncode != 0:
|
|
 |
7f5c89 |
+ raise CmdError(cmd_args, returncode,
|
|
 |
7f5c89 |
+ 'failed %s' % (', '.join(cmd_args)),
|
|
 |
7f5c89 |
+ stdout, stderr)
|
|
 |
7f5c89 |
+ return stdout, stderr
|
|
 |
7f5c89 |
+ except OSError as e:
|
|
 |
7f5c89 |
+ raise CmdError(cmd_args, e.errno, stderr=str(e))
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def password_callback(slot, retry):
|
|
 |
7f5c89 |
return db_passwd
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
-#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def nickname_collision_callback(old_nickname, cert):
|
|
 |
7f5c89 |
cancel = False
|
|
 |
7f5c89 |
@@ -44,6 +70,51 @@
|
|
 |
7f5c89 |
return new_nickname, cancel
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
+def get_cert_der_from_db(nickname):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-d', db_name,
|
|
 |
7f5c89 |
+ '-L',
|
|
 |
7f5c89 |
+ '-n', nickname]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ try:
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ except CmdError as e:
|
|
 |
7f5c89 |
+ if e.returncode == 255 and 'not found' in e.stderr:
|
|
 |
7f5c89 |
+ return None
|
|
 |
7f5c89 |
+ else:
|
|
 |
7f5c89 |
+ raise
|
|
 |
7f5c89 |
+ return stdout
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def delete_cert_from_db(nickname):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/certutil',
|
|
 |
7f5c89 |
+ '-d', db_name,
|
|
 |
7f5c89 |
+ '-D',
|
|
 |
7f5c89 |
+ '-n', nickname]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ run_cmd(cmd_args)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def create_pk12(nickname, filename):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/pk12util',
|
|
 |
7f5c89 |
+ '-o', filename,
|
|
 |
7f5c89 |
+ '-n', nickname,
|
|
 |
7f5c89 |
+ '-d', db_name,
|
|
 |
7f5c89 |
+ '-K', db_passwd,
|
|
 |
7f5c89 |
+ '-W', pk12_passwd]
|
|
 |
7f5c89 |
+ run_cmd(cmd_args)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def list_pk12(filename):
|
|
 |
7f5c89 |
+ cmd_args = ['/usr/bin/pk12util',
|
|
 |
7f5c89 |
+ '-l', filename,
|
|
 |
7f5c89 |
+ '-W', pk12_passwd]
|
|
 |
7f5c89 |
+ stdout, stderr = run_cmd(cmd_args)
|
|
 |
7f5c89 |
+ return stdout
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def strip_key_from_pk12_listing(text):
|
|
 |
7f5c89 |
+ match = re.search(r'^Certificate:$', text, re.MULTILINE)
|
|
 |
7f5c89 |
+ if not match:
|
|
 |
7f5c89 |
+ raise ValueError('Could not file Key section in pk12 listing')
|
|
 |
7f5c89 |
+ return text[match.start(0):]
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def load_tests(loader, tests, pattern):
|
|
 |
7f5c89 |
@@ -59,22 +130,23 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
class TestPKCS12Decoder(unittest.TestCase):
|
|
 |
7f5c89 |
def setUp(self):
|
|
 |
7f5c89 |
- nss.nss_init_read_write(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init_read_write(db_name)
|
|
 |
7f5c89 |
nss.set_password_callback(password_callback)
|
|
 |
7f5c89 |
nss.pkcs12_set_nickname_collision_callback(nickname_collision_callback)
|
|
 |
7f5c89 |
nss.pkcs12_enable_all_ciphers()
|
|
 |
7f5c89 |
+ self.cert_der = get_cert_der_from_db(cert_nickname)
|
|
 |
7f5c89 |
+ if self.cert_der is None:
|
|
 |
7f5c89 |
+ raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def tearDown(self):
|
|
 |
7f5c89 |
nss.nss_shutdown()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def test_read(self):
|
|
 |
7f5c89 |
if verbose: print "test_read"
|
|
 |
7f5c89 |
- cmd='pk12util -o %s -n %s -d pki -K %s -W %s' % \
|
|
 |
7f5c89 |
- (read_pkcs12_file, read_nickname, db_passwd, pkcs12_file_password)
|
|
 |
7f5c89 |
- run_cmd(cmd)
|
|
 |
7f5c89 |
+ create_pk12(cert_nickname, pk12_filename)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
slot = nss.get_internal_key_slot()
|
|
 |
7f5c89 |
- pkcs12 = nss.PKCS12Decoder(read_pkcs12_file, pkcs12_file_password, slot)
|
|
 |
7f5c89 |
+ pkcs12 = nss.PKCS12Decoder(pk12_filename, pk12_passwd, slot)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
self.assertEqual(len(pkcs12), 3)
|
|
 |
7f5c89 |
cert_bag_count = 0
|
|
 |
7f5c89 |
@@ -102,33 +174,43 @@
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def test_import(self):
|
|
 |
7f5c89 |
if verbose: print "test_import"
|
|
 |
7f5c89 |
- cmd='certutil -d pki -D -n %s' % (read_nickname)
|
|
 |
7f5c89 |
- run_cmd(cmd)
|
|
 |
7f5c89 |
+ delete_cert_from_db(cert_nickname)
|
|
 |
7f5c89 |
+ self.assertEqual(get_cert_der_from_db(cert_nickname), None)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
slot = nss.get_internal_key_slot()
|
|
 |
7f5c89 |
- pkcs12 = nss.PKCS12Decoder(read_pkcs12_file, pkcs12_file_password, slot)
|
|
 |
7f5c89 |
+ pkcs12 = nss.PKCS12Decoder(pk12_filename, pk12_passwd, slot)
|
|
 |
7f5c89 |
slot.authenticate()
|
|
 |
7f5c89 |
pkcs12.database_import()
|
|
 |
7f5c89 |
+ cert_der = get_cert_der_from_db(cert_nickname)
|
|
 |
7f5c89 |
+ self.assertEqual(cert_der, self.cert_der)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
#-------------------------------------------------------------------------------
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
class TestPKCS12Export(unittest.TestCase):
|
|
 |
7f5c89 |
def setUp(self):
|
|
 |
7f5c89 |
- nss.nss_init(certdir)
|
|
 |
7f5c89 |
+ nss.nss_init(db_name)
|
|
 |
7f5c89 |
nss.set_password_callback(password_callback)
|
|
 |
7f5c89 |
nss.pkcs12_enable_all_ciphers()
|
|
 |
7f5c89 |
+ self.cert_der = get_cert_der_from_db(cert_nickname)
|
|
 |
7f5c89 |
+ if self.cert_der is None:
|
|
 |
7f5c89 |
+ raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def tearDown(self):
|
|
 |
7f5c89 |
nss.nss_shutdown()
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
def test_export(self):
|
|
 |
7f5c89 |
if verbose: print "test_export"
|
|
 |
7f5c89 |
- pkcs12_data = nss.pkcs12_export(export_nickname, pkcs12_file_password)
|
|
 |
7f5c89 |
- if write_export_file:
|
|
 |
7f5c89 |
- p12_file_path = os.path.join(os.path.dirname(sys.argv[0]), "%s.p12" % export_nickname)
|
|
 |
7f5c89 |
- f = open(p12_file_path, 'w')
|
|
 |
7f5c89 |
+ pkcs12_data = nss.pkcs12_export(cert_nickname, pk12_passwd)
|
|
 |
7f5c89 |
+ with open(exported_pk12_filename, 'w') as f:
|
|
 |
7f5c89 |
f.write(pkcs12_data)
|
|
 |
7f5c89 |
- f.close()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ pk12_listing = list_pk12(pk12_filename)
|
|
 |
7f5c89 |
+ pk12_listing = strip_key_from_pk12_listing(pk12_listing)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ exported_pk12_listing = list_pk12(exported_pk12_filename)
|
|
 |
7f5c89 |
+ exported_pk12_listing = strip_key_from_pk12_listing(exported_pk12_listing)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ self.assertEqual(pk12_listing, exported_pk12_listing)
|
|
 |
7f5c89 |
|
|
 |
7f5c89 |
if __name__ == '__main__':
|
|
 |
7f5c89 |
unittest.main()
|
|
 |
7f5c89 |
diff -N -u -r python-nss-0.14.0/test/util.py python-nss-0.14.1/test/util.py
|
|
 |
7f5c89 |
--- python-nss-0.14.0/test/util.py 1969-12-31 19:00:00.000000000 -0500
|
|
 |
7f5c89 |
+++ python-nss-0.14.1/test/util.py 2013-06-13 09:58:32.000000000 -0400
|
|
 |
7f5c89 |
@@ -0,0 +1,40 @@
|
|
 |
7f5c89 |
+import sys
|
|
 |
7f5c89 |
+import os
|
|
 |
7f5c89 |
+from distutils.util import get_platform
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def get_build_dir():
|
|
 |
7f5c89 |
+ '''
|
|
 |
7f5c89 |
+ Walk from the current directory up until a directory is found
|
|
 |
7f5c89 |
+ which contains a regular file called "setup.py" and a directory
|
|
 |
7f5c89 |
+ called "build". If found return the fully qualified path to
|
|
 |
7f5c89 |
+ the build directory's platform specific directory, this is where
|
|
 |
7f5c89 |
+ the architecture specific build produced by setup.py is located.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ There is no API in distutils to return the platform specific
|
|
 |
7f5c89 |
+ directory so we use as much as distutils exposes, the rest was
|
|
 |
7f5c89 |
+ determined by looking at the source code for distutils.
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ If the build directory cannont be found in the tree None is returned.
|
|
 |
7f5c89 |
+ '''
|
|
 |
7f5c89 |
+ cwd = os.getcwd()
|
|
 |
7f5c89 |
+ path_components = cwd.split('/')
|
|
 |
7f5c89 |
+ while (len(path_components)):
|
|
 |
7f5c89 |
+ path = os.path.join('/', *path_components)
|
|
 |
7f5c89 |
+ setup_path = os.path.join(path, 'setup.py')
|
|
 |
7f5c89 |
+ build_path = os.path.join(path, 'build')
|
|
 |
7f5c89 |
+ # Does this directory contain the file "setup.py" and the directory "build"?
|
|
 |
7f5c89 |
+ if os.path.exists(setup_path) and os.path.exists(build_path) and \
|
|
 |
7f5c89 |
+ os.path.isfile(setup_path) and os.path.isdir(build_path):
|
|
 |
7f5c89 |
+ # Found, return the path contentated with the architecture
|
|
 |
7f5c89 |
+ # specific build directory
|
|
 |
7f5c89 |
+ platform_specifier = "lib.%s-%s" % (get_platform(), sys.version[0:3])
|
|
 |
7f5c89 |
+ return os.path.join(build_path, platform_specifier)
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Not found, ascend to parent directory and try again
|
|
 |
7f5c89 |
+ path_components.pop()
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+ # Failed to find the build directory
|
|
 |
7f5c89 |
+ return None
|
|
 |
7f5c89 |
+
|
|
 |
7f5c89 |
+def insert_build_dir_into_path():
|
|
 |
7f5c89 |
+ sys.path.insert(0,get_build_dir())
|