diff --git a/.python-nss.metadata b/.python-nss.metadata
new file mode 100644
index 0000000..12dcef1
--- /dev/null
+++ b/.python-nss.metadata
@@ -0,0 +1 @@
+dd0d0b434b3489fa52fabe4d7e32a9208c2a3a98 SOURCES/python-nss-0.14.0.tar.bz2
diff --git a/README.md b/README.md
deleted file mode 100644
index 0e7897f..0000000
--- a/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The master branch has no content
- 
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
- 
-If you find this file in a distro specific branch, it means that no content has been checked in yet
diff --git a/SOURCES/python-nss-0.14.1.patch b/SOURCES/python-nss-0.14.1.patch
new file mode 100644
index 0000000..75ba600
--- /dev/null
+++ b/SOURCES/python-nss-0.14.1.patch
@@ -0,0 +1,2416 @@
+diff -N -u -r python-nss-0.14.0/doc/ChangeLog python-nss-0.14.1/doc/ChangeLog
+--- python-nss-0.14.0/doc/ChangeLog	2013-05-02 17:29:27.000000000 -0400
++++ python-nss-0.14.1/doc/ChangeLog	2013-10-09 09:35:29.000000000 -0400
+@@ -1,5 +1,37 @@
+-2013-04-24  John Dennis  <jdennis@redhat.com> 0.14.0
+-  External Changes
++2013-10-09  John Dennis  <jdennis@redhat.com> 0.14.1
++
++  Modifications only to tests and examples.
++
++  * Fix bug in ssl_example.py and test_client_server.py where complete
++    data was not read from socket. The Beast CVE fix in NSS causes
++    only one octet to be sent in the first socket packet and then the
++    remaining data is sent normally, this is known as 1/n-1 record
++    splitting. The example and test SSL code sent short messages and
++    then did a sock.recv(1024). We had always received the entire
++    message in one sock.recv() call because it was so short. But
++    sock.recv() does not guarantee how much data will be received,
++    thus this was a coding mistake. The solution is straight forward,
++    use newlines as a record separator and call sock.readline()
++    instead of sock.recv(). sock.readline() calls sock.recv()
++    internally until a complete line is read or the socket is closed.
++
++  * Rewrite setup_certs.py, it was written like an expect script
++    reacting to prompts read from a pseudo terminal but it was fragile
++    and would hang on some systems. New version uses temporary
++    password file and writes hardcoded responses to the stdin of
++    certuil and modutil.
++
++  * setup_certs now creates a new sql sytle NSS database (sql:pki)
++
++  * All tests and examples now load the sql:pki database. Command line
++    arg and variable changed from dbdir to db_name to reflect the
++    database specification is no longer just a directory.
++
++  * All command line process in test and examples now uses modern
++    argparse module instead of deprecated getopt and optparse. Some
++    command line args were tweaked.
++
++2013-04-24 John Dennis <jdennis@redhat.com> 0.14.0 External Changes
+   ----------------
+ 
+   The primary enhancements in this version is support of certifcate
+diff -N -u -r python-nss-0.14.0/doc/examples/cert_dump.py python-nss-0.14.1/doc/examples/cert_dump.py
+--- python-nss-0.14.0/doc/examples/cert_dump.py	2013-04-23 13:36:53.000000000 -0400
++++ python-nss-0.14.1/doc/examples/cert_dump.py	2013-10-08 12:59:24.000000000 -0400
+@@ -18,10 +18,10 @@
+ components of a cert.
+ '''
+ 
++import argparse
++import getpass
+ import os
+ import sys
+-import getopt
+-import getpass
+ 
+ from nss.error import NSPRError
+ import nss.io as io
+@@ -93,57 +93,34 @@
+ 
+ # -----------------------------------------------------------------------------
+ 
+-usage_str = '''
+--p --pem        read the certifcate in PEM ascii format (default)
+--d --der        read the certifcate in DER binary format
+--P --print-cert print the cert using the internal rendering code
+-'''
+-
+-def usage():
+-    print usage_str
+-
+-try:
+-    opts, args = getopt.getopt(sys.argv[1:], "hpdP",
+-                               ["help", "pem", "der", "print-cert"])
+-except getopt.GetoptError:
+-    # print help information and exit:
+-    usage()
+-    sys.exit(2)
+-
+-
+-filename = 'cert.der'
+-is_pem_format = True
+-print_cert = False
+-
+-for o, a in opts:
+-    if o in ("-H", "--help"):
+-        usage()
+-        sys.exit()
+-    elif o in ("-p", "--pem"):
+-        is_pem_format = True
+-    elif o in ("-d", "--der"):
+-        is_pem_format = False
+-    elif o in ("-P", "--print-cert"):
+-        print_cert = True
+-
+-
+-filename = sys.argv[1]
++parser = argparse.ArgumentParser(description='cert formatting example',
++                                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
++parser.add_argument('-f', '--cert-format', choices=['pem', 'der'],
++                    help='format of input cert')
++parser.add_argument('-p', '--print-cert', action='store_true',
++                    help='print the cert using the internal rendering code')
++parser.add_argument('cert_file', nargs=1,
++                    help='input cert file to process')
++
++parser.set_defaults(cert_format='pem',
++                    print_cert=False
++                    )
++options = parser.parse_args()
+ 
+ # Perform basic configuration and setup
+ nss.nss_init_nodb()
+ 
+-if len(args):
+-    filename = args[0]
++filename = options.cert_file[0]
+ 
+ print "certificate filename=%s" % (filename)
+ 
+ # Read the certificate as DER encoded data
+-si = nss.read_der_from_file(filename, is_pem_format)
++si = nss.read_der_from_file(filename, options.cert_format == 'pem')
+ # Parse the DER encoded data returning a Certificate object
+ cert = nss.Certificate(si)
+ 
+ # Useful for comparing the internal cert rendering to what this script generates.
+-if print_cert:
++if options.print_cert:
+     print cert
+ 
+ # Get the extension list from the certificate
+diff -N -u -r python-nss-0.14.0/doc/examples/httplib_example.py python-nss-0.14.1/doc/examples/httplib_example.py
+--- python-nss-0.14.0/doc/examples/httplib_example.py	2013-04-15 13:05:46.000000000 -0400
++++ python-nss-0.14.1/doc/examples/httplib_example.py	2013-10-08 13:04:03.000000000 -0400
+@@ -4,13 +4,13 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ 
+-import sys
++import argparse
+ import errno
+-import getopt
+-import urlparse
+-import httplib
+ import getpass
++import httplib
+ import logging
++import sys
++import urlparse
+ 
+ from nss.error import NSPRError
+ import nss.io as io
+@@ -19,14 +19,6 @@
+ 
+ #------------------------------------------------------------------------------
+ 
+-httplib_debug_level = 0
+-logging_debug_level = logging.INFO
+-certdir = 'pki'
+-password = ''
+-nickname = ''
+-url = 'https://sourceforge.net/projects/python'
+-use_ssl = True
+-use_connection_class = True
+ timeout_secs = 3
+ 
+ #------------------------------------------------------------------------------
+@@ -94,28 +86,6 @@
+     logging.debug('cert valid %s for "%s"', cert_is_valid,  cert.subject)
+     return cert_is_valid
+ 
+-def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
+-    cert = None
+-    if chosen_nickname:
+-        try:
+-            cert = nss.find_cert_from_nickname(chosen_nickname, password)
+-            priv_key = nss.find_key_by_any_cert(cert, password)
+-            return cert, priv_key
+-        except NSPRError:
+-            return False
+-    else:
+-        nicknames = nss.get_cert_nicknames(certdb, nss.SEC_CERT_NICKNAMES_USER)
+-        for nickname in nicknames:
+-            try:
+-                cert = nss.find_cert_from_nickname(nickname, password)
+-                if cert.check_valid_times():
+-                    if cert.has_signer_in_ca_names(ca_names):
+-                        priv_key = nss.find_key_by_any_cert(cert, password)
+-                        return cert, priv_key
+-            except NSPRError:
+-                return False
+-        return False
+-
+ def password_callback(slot, retry, password):
+     if not retry and password: return password
+     return getpass.getpass("Enter password for %s: " % slot.token_name);
+@@ -136,7 +106,7 @@
+         if not dbdir:
+             raise RuntimeError("dbdir is required")
+ 
+-        logging.debug('%s init %s', self.__class__.__name__, host)
++        logging.debug('%s init host=%s dbdir=%s', self.__class__.__name__, host, dbdir)
+         if not nss.nss_is_initialized(): nss.nss_init(dbdir)
+         self.sock = None
+         ssl.set_domestic_policy()
+@@ -231,33 +201,46 @@
+ #------------------------------------------------------------------------------
+ 
+ 
+-opts, args = getopt.getopt(sys.argv[1:],
+-                           'Dd:n:w:sScC',
+-                           ['debuglevel','certdir=','nickname=','password=',
+-                            'use-ssl', 'no-ssl', 'use-connection-class', 'no-connection-class'])
+-for o, a in opts:
+-    if o in('-D', '--httplib_debug_level'):
+-        httplib_debug_level = httplib_debug_level + 1
+-    elif o in ("-d", "--certdir"):
+-        certdir = a
+-    elif o in ("-n", "--nickname"):
+-        nickname = a
+-    elif o in ("-w", "--password"):
+-        password = a
+-    elif o in ("-s", "--use-ssl"):
+-        use_ssl = True
+-    elif o in ("-S", "--no-ssl"):
+-        use_ssl = False
+-    elif o in ("-c", "--use-connection-class"):
+-        use_connection_class = True
+-    elif o in ("-C", "--no-connection-class"):
+-        use_connection_class = False
++parser = argparse.ArgumentParser(description='httplib example')
+ 
+-if len(args) > 0:
+-    url = args[0]
++parser.add_argument('-d', '--db-name',
++                    help='NSS database name (e.g. "sql:pki")')
+ 
++parser.add_argument('--db-passwd',
++                    help='NSS database password')
+ 
+-if httplib_debug_level > 0:
++parser.add_argument('-s', '--ssl', dest='use_ssl', action='store_true',
++                    help='use SSL connection')
++
++parser.add_argument('-S', '--no-ssl', dest='use_ssl', action='store_false',
++                    help='do not use SSL connection')
++
++parser.add_argument('-c', '--connection-class', dest='use_connection_class', action='store_true',
++                    help='use connection class')
++
++parser.add_argument('-C', '--no-connection-class', dest='use_connection_class', action='store_false',
++                    help='do not use connection class')
++
++parser.add_argument('-D', '--httplib-debug-level', action='count',
++                    help='httplib debug level')
++
++parser.add_argument('url', nargs=1,
++                    help='URL to open (e.g. "https://sourceforge.net/projects/python"')
++
++parser.set_defaults(db_name = 'sql:pki',
++                    db_passwd = 'db_passwd',
++                    httplib_debug_level = 0,
++                    use_ssl = True,
++                    use_connection_class = True,
++                    )
++
++options = parser.parse_args()
++
++
++url = options.url[0]
++
++logging_debug_level = logging.INFO
++if options.httplib_debug_level > 0:
+     logging_debug_level = logging.DEBUG
+ else:
+     logging_debug_level = logging.INFO
+@@ -269,7 +252,7 @@
+ # Perform basic configuration and setup
+ 
+ url_components = urlparse.urlsplit(url)
+-if use_ssl:
++if options.use_ssl:
+     url_components.schema = 'https'
+ else:
+     url_components.schema = 'http'
+@@ -280,14 +263,14 @@
+     print "ERROR: bad url \"%s\"" % (url)
+     sys.exit(1)
+ 
+-if use_connection_class:
+-    if use_ssl:
++if options.use_connection_class:
++    if options.use_ssl:
+         logging.info("Start (using NSSConnection class) %s", url)
+-        conn = NSSConnection(url_components.netloc, 443, dbdir="/etc/pki/nssdb")
++        conn = NSSConnection(url_components.netloc, 443, dbdir=options.db_name)
+     else:
+         logging.info("Start (using NSPRConnection class) %s", url)
+         conn = NSPRConnection(url_components.netloc, 80)
+-    conn.set_debuglevel(httplib_debug_level)
++    conn.set_debuglevel(options.httplib_debug_level)
+     conn.connect()
+     conn.request("GET", "/")
+     response = conn.getresponse()
+@@ -302,13 +285,13 @@
+     print data
+     conn.close()
+ else:
+-    if use_ssl:
++    if options.use_ssl:
+         logging.info("Start (using NSSHTTPS class) %s", url)
+-        h = NSSHTTPS(url_components.netloc, 443, dbdir="/etc/pki/nssdb")
++        h = NSSHTTPS(url_components.netloc, 443, dbdir=options.db_name)
+     else:
+         logging.info("Start (using NSPRHTTP class) %s", url)
+         h = NSPRHTTP(url_components.netloc, 80)
+-    h.set_debuglevel(httplib_debug_level)
++    h.set_debuglevel(options.httplib_debug_level)
+     h.connect()
+     h.putrequest('GET', '/')
+     h.endheaders()
+diff -N -u -r python-nss-0.14.0/doc/examples/ssl_example.py python-nss-0.14.1/doc/examples/ssl_example.py
+--- python-nss-0.14.0/doc/examples/ssl_example.py	2013-04-15 13:05:46.000000000 -0400
++++ python-nss-0.14.1/doc/examples/ssl_example.py	2013-10-09 00:07:54.000000000 -0400
+@@ -7,10 +7,10 @@
+ import warnings
+ warnings.simplefilter( "always", DeprecationWarning)
+ 
++import argparse
++import getpass
+ import os
+ import sys
+-import getopt
+-import getpass
+ 
+ from nss.error import NSPRError
+ import nss.io as io
+@@ -24,19 +24,7 @@
+ REQUEST_CLIENT_CERT_ALWAYS = 3
+ REQUIRE_CLIENT_CERT_ALWAYS = 4
+ 
+-# command line parameters, default them to something reasonable
+-client = False
+-server = False
+-password = 'db_passwd'
+-use_ssl = True
+-client_cert_action = NO_CLIENT_CERT
+-certdir = 'pki'
+-hostname = os.uname()[1]
+-server_nickname = 'test_server'
+-client_nickname = 'test_user'
+-port = 1234
+ timeout_secs = 3
+-family = io.PR_AF_UNSPEC
+ 
+ # -----------------------------------------------------------------------------
+ # Utility Functions
+@@ -63,7 +51,7 @@
+     if pin_args is None:
+         pin_args = ()
+ 
+-    print "cert:\n%s" % cert
++    print "peer cert:\n%s" % cert
+ 
+     # Define how the cert is being used based upon the is_server flag.  This may
+     # seem backwards, but isn't. If we're a server we're trying to validate a
+@@ -149,30 +137,30 @@
+     valid_addr = False
+     # Get the IP Address of our server
+     try:
+-        addr_info = io.AddrInfo(hostname)
++        addr_info = io.AddrInfo(options.hostname)
+     except Exception, e:
+-        print "could not resolve host address \"%s\"" % hostname
++        print "could not resolve host address \"%s\"" % options.hostname
+         return
+ 
+     for net_addr in addr_info:
+-        if family != io.PR_AF_UNSPEC:
+-            if net_addr.family != family: continue
+-        net_addr.port = port
++        if options.family != io.PR_AF_UNSPEC:
++            if net_addr.family != options.family: continue
++        net_addr.port = options.port
+ 
+-        if use_ssl:
++        if options.use_ssl:
+             sock = ssl.SSLSocket(net_addr.family)
+ 
+             # Set client SSL socket options
+             sock.set_ssl_option(ssl.SSL_SECURITY, True)
+             sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
+-            sock.set_hostname(hostname)
++            sock.set_hostname(options.hostname)
+ 
+             # Provide a callback which notifies us when the SSL handshake is complete
+             sock.set_handshake_callback(handshake_callback)
+ 
+             # Provide a callback to supply our client certificate info
+-            sock.set_client_auth_data_callback(client_auth_data_callback, client_nickname,
+-                                               password, nss.get_default_certdb())
++            sock.set_client_auth_data_callback(client_auth_data_callback, options.client_nickname,
++                                               options.password, nss.get_default_certdb())
+ 
+             # Provide a callback to verify the servers certificate
+             sock.set_auth_certificate_callback(auth_certificate_callback,
+@@ -192,17 +180,18 @@
+ 
+     if not valid_addr:
+         print "Could not establish valid address for \"%s\" in family %s" % \
+-        (hostname, io.addr_family_name(family))
++        (options.hostname, io.addr_family_name(options.family))
+         return
+ 
+     # Talk to the server
+     try:
+-        sock.send("Hello")
+-        buf = sock.recv(1024)
++        sock.send('Hello' + '\n') # newline is protocol record separator
++        buf = sock.readline()
+         if not buf:
+             print "client lost connection"
+             sock.close()
+             return
++        buf = buf.rstrip()        # remove newline record separator
+         print "client received: %s" % (buf)
+     except Exception, e:
+         print e.strerror
+@@ -221,7 +210,7 @@
+ 
+     try:
+         sock.close()
+-        if use_ssl:
++        if options.use_ssl:
+             ssl.clear_session_cache()
+     except Exception, e:
+         print e
+@@ -231,36 +220,34 @@
+ # -----------------------------------------------------------------------------
+ 
+ def Server():
+-    global family
+-
+-    # Perform basic SSL server configuration
+-    ssl.set_default_cipher_pref(ssl.SSL_RSA_WITH_NULL_MD5, True)
+-    ssl.config_server_session_id_cache()
+-
+-    # Get our certificate and private key
+-    server_cert = nss.find_cert_from_nickname(server_nickname, password)
+-    priv_key = nss.find_key_by_any_cert(server_cert, password)
+-    server_cert_kea = server_cert.find_kea_type();
+-
+-    print "server cert:\n%s" % server_cert
+-
+     # Setup an IP Address to listen on any of our interfaces
+-    if family == io.PR_AF_UNSPEC:
+-        family = io.PR_AF_INET
+-    net_addr = io.NetworkAddress(io.PR_IpAddrAny, port, family)
++    if options.family == io.PR_AF_UNSPEC:
++        options.family = io.PR_AF_INET
++    net_addr = io.NetworkAddress(io.PR_IpAddrAny, options.port, options.family)
++
++    if options.use_ssl:
++        # Perform basic SSL server configuration
++        ssl.set_default_cipher_pref(ssl.SSL_RSA_WITH_NULL_MD5, True)
++        ssl.config_server_session_id_cache()
++
++        # Get our certificate and private key
++        server_cert = nss.find_cert_from_nickname(options.server_nickname, options.password)
++        priv_key = nss.find_key_by_any_cert(server_cert, options.password)
++        server_cert_kea = server_cert.find_kea_type();
++
++        print "server cert:\n%s" % server_cert
+ 
+-    if use_ssl:
+         sock = ssl.SSLSocket(net_addr.family)
+ 
+         # Set server SSL socket options
+-        sock.set_pkcs11_pin_arg(password)
++        sock.set_pkcs11_pin_arg(options.password)
+         sock.set_ssl_option(ssl.SSL_SECURITY, True)
+         sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_SERVER, True)
+ 
+         # If we're doing client authentication then set it up
+-        if client_cert_action >= REQUEST_CLIENT_CERT_ONCE:
++        if options.client_cert_action >= REQUEST_CLIENT_CERT_ONCE:
+             sock.set_ssl_option(ssl.SSL_REQUEST_CERTIFICATE, True)
+-        if client_cert_action == REQUIRE_CLIENT_CERT_ONCE:
++        if options.client_cert_action == REQUIRE_CLIENT_CERT_ONCE:
+             sock.set_ssl_option(ssl.SSL_REQUIRE_CERTIFICATE, True)
+         sock.set_auth_certificate_callback(auth_certificate_callback, nss.get_default_certdb())
+ 
+@@ -278,7 +265,7 @@
+     while True:
+         # Accept a connection from a client
+         client_sock, client_addr = sock.accept()
+-        if use_ssl:
++        if options.use_ssl:
+             client_sock.set_handshake_callback(handshake_callback)
+ 
+         print "client connect from: %s" % (client_addr)
+@@ -286,14 +273,15 @@
+         while True:
+             try:
+                 # Handle the client connection
+-                buf = client_sock.recv(1024)
++                buf = client_sock.readline()
+                 if not buf:
+                     print "server lost lost connection to %s" % (client_addr)
+                     break
+ 
++                buf = buf.rstrip()                 # remove newline record separator
+                 print "server received: %s" % (buf)
+ 
+-                client_sock.send("Goodbye")
++                client_sock.send('Goodbye' + '\n') # newline is protocol record separator
+                 try:
+                     client_sock.shutdown(io.PR_SHUTDOWN_RCV)
+                     client_sock.close()
+@@ -308,7 +296,7 @@
+     try:
+         sock.shutdown()
+         sock.close()
+-        if use_ssl:
++        if options.use_ssl:
+             ssl.shutdown_server_session_id_cache()
+     except Exception, e:
+         print e
+@@ -316,141 +304,121 @@
+ 
+ # -----------------------------------------------------------------------------
+ 
+-usage_str = '''
+--C --client     run as the client (default: %(client)s)
+--S --server     run as the server (default: %(server)s)
+--d --certdir    certificate directory (default: %(certdir)s)
+--h --hostname   host to connect to (default: %(hostname)s)
+--f --family     may be inet|inet6|unspec (default: %(family)s)
+-                if unspec client tries all addresses returned by AddrInfo
+-                          server binds to IPv4 "any" wildcard address
+-                if inet   client tries IPv4 addresses returned by AddrInfo
+-                          server binds to IPv4 "any" wildcard address
+-                if inet6  client tries IPv6 addresses returned by AddrInfo
+-                          server binds to IPv6 "any" wildcard address
+--4 --inet       set family to inet (see family)
+--6 --inet6      set family to inet6 (see family)
+--n --server_nickname server certificate nickname (default: %(server_nickname)s)
+--N --client_nickname client certificate nickname (default: %(client_nickname)s)
+--w --password   certificate database password (default: %(password)s)
+--p --port       host port (default: %(port)s)
+--e --encrypt    use SSL (default) (default: %(encrypt)s)
+--E --noencrypt  don't use SSL (default: %(noencrypt)s)
+--f --require_cert_once (default: %(require_cert_once)s)
+--F --require_cert_always (default: %(require_cert_always)s)
+--r --request_cert_once (default: %(request_cert_once)s)
+--R --request_cert_always (default: %(request_cert_always)s)
+--H --help
+-''' % {
+-       'client'              : client,
+-       'server'              : server,
+-       'certdir'             : certdir,
+-       'hostname'            : hostname,
+-       'family'              : io.addr_family_name(family),
+-       'server_nickname'     : server_nickname,
+-       'client_nickname'     : client_nickname,
+-       'password'            : password,
+-       'port'                : port,
+-       'encrypt'             : use_ssl is True,
+-       'noencrypt'           : use_ssl is False,
+-       'require_cert_once'   : client_cert_action == REQUIRE_CLIENT_CERT_ONCE,
+-       'require_cert_always' : client_cert_action == REQUIRE_CLIENT_CERT_ALWAYS,
+-       'request_cert_once'   : client_cert_action == REQUEST_CLIENT_CERT_ONCE,
+-       'request_cert_always' : client_cert_action == REQUEST_CLIENT_CERT_ALWAYS,
+-       }
+-
+-def usage():
+-    print usage_str
+-
+-try:
+-    opts, args = getopt.getopt(sys.argv[1:], "Hd:h:f:46n:N:w:p:CSeE",
+-                               ["help", "certdir=", "hostname=",
+-                                "family", "inet", "inet6",
+-                                "server_nickname=", "client_nickname=",
+-                                "password=", "port=",
+-                                "client", "server", "encrypt", "noencrypt",
+-                                "require_cert_once", "require_cert_always",
+-                                "request_cert_once", "request_cert_always",
+-                                ])
+-except getopt.GetoptError:
+-    # print help information and exit:
+-    usage()
+-    sys.exit(2)
+-
+-
+-for o, a in opts:
+-    if o in ("-d", "--certdir"):
+-        certdir = a
+-    elif o in ("-h", "--hostname"):
+-        hostname = a
+-    elif o in ("-f", "--family"):
+-        if a == "inet":
++class FamilyArgAction(argparse.Action):
++    def __call__(self, parser, namespace, values, option_string=None):
++        value = values[0]
++        if value == "inet":
+             family = io.PR_AF_INET
+-        elif a == "inet6":
++        elif value == "inet6":
+             family = io.PR_AF_INET6
+-        elif a == "unspec":
++        elif value == "unspec":
+             family = io.PR_AF_UNSPEC
+         else:
+-            print "unknown address family (%s)" % (a)
+-            usage()
+-            sys.exit()
+-    elif o in ("-4", "--inet"):
+-        family = io.PR_AF_INET
+-    elif o in ("-6", "--inet6"):
+-        family = io.PR_AF_INET6
+-    elif o in ("-n", "--server_nickname"):
+-        server_nickname = a
+-    elif o in ("-N", "--client_nickname"):
+-        client_nickname = a
+-    elif o in ("-w", "--password"):
+-        password = a
+-    elif o in ("-p", "--port"):
+-        port = int(a)
+-    elif o in ("-C", "--client"):
+-        client = True
+-    elif o in ("-S", "--server"):
+-        server = True
+-    elif o in ("-e", "--encrypt"):
+-        use_ssl = True
+-    elif o in ("-E", "--noencrypt"):
+-        use_ssl = False
+-    elif o in ("--require_cert_once"):
+-        client_cert_action = REQUIRE_CLIENT_CERT_ONCE
+-    elif o in ("--require_cert_always"):
+-        client_cert_action = REQUIRE_CLIENT_CERT_ALWAYS
+-    elif o in ("--request_cert_once"):
+-        client_cert_action = REQUEST_CLIENT_CERT_ONCE
+-    elif o in ("--request_cert_always"):
+-        client_cert_action = REQUEST_CLIENT_CERT_ALWAYS
+-    elif o in ("-H", "--help"):
+-        usage()
+-        sys.exit()
+-    else:
+-        usage()
+-        sys.exit()
++            raise argparse.ArgumentError(self, "unknown address family (%s)" % (value))
++        setattr(namespace, self.dest, family)
++
++parser = argparse.ArgumentParser(description='SSL example')
++
++parser.add_argument('-C', '--client', action='store_true',
++                    help='run as the client')
++
++parser.add_argument('-S', '--server', action='store_true',
++                    help='run as the server')
++
++parser.add_argument('-d', '--db-name',
++                    help='NSS database name (e.g. "sql:pki")')
++
++parser.add_argument('-H', '--hostname',
++                    help='host to connect to')
++
++parser.add_argument('-f', '--family',
++                    choices=['unspec', 'inet', 'inet6'],
++                    dest='family', action=FamilyArgAction, nargs=1,
++                    help='''
++                      If unspec client tries all addresses returned by AddrInfo,
++                      server binds to IPv4 "any" wildcard address.
++
++                      If inet client tries IPv4 addresses returned by AddrInfo,
++                      server binds to IPv4 "any" wildcard address.
++
++                      If inet6 client tries IPv6 addresses returned by AddrInfo,
++                      server binds to IPv6 "any" wildcard address''')
+ 
+-if client and server:
++parser.add_argument('-4', '--inet',
++                    dest='family', action='store_const', const=io.PR_AF_INET,
++                    help='set family to inet (see family)')
++
++parser.add_argument('-6', '--inet6',
++                    dest='family', action='store_const', const=io.PR_AF_INET6,
++                    help='set family to inet6 (see family)')
++
++parser.add_argument('-n', '--server-nickname',
++                    help='server certificate nickname')
++
++parser.add_argument('-N', '--client-nickname',
++                    help='client certificate nickname')
++
++parser.add_argument('-w', '--password',
++                    help='certificate database password')
++
++parser.add_argument('-p', '--port', type=int,
++                    help='host port')
++
++parser.add_argument('-e', '--encrypt', dest='use_ssl', action='store_true',
++                    help='use SSL connection')
++
++parser.add_argument('-E', '--no-encrypt', dest='use_ssl', action='store_false',
++                    help='do not use SSL connection')
++
++parser.add_argument('--require-cert-once', dest='client_cert_action',
++                    action='store_const', const=REQUIRE_CLIENT_CERT_ONCE)
++
++parser.add_argument('--require-cert-always', dest='client_cert_action',
++                    action='store_const', const=REQUIRE_CLIENT_CERT_ALWAYS)
++
++parser.add_argument('--request-cert-once', dest='client_cert_action',
++                    action='store_const', const=REQUEST_CLIENT_CERT_ONCE)
++
++parser.add_argument('--request-cert-always', dest='client_cert_action',
++                    action='store_const', const=REQUEST_CLIENT_CERT_ALWAYS)
++
++parser.set_defaults(client = False,
++                    server = False,
++                    db_name = 'sql:pki',
++                    hostname = os.uname()[1],
++                    family = io.PR_AF_UNSPEC,
++                    server_nickname = 'test_server',
++                    client_nickname = 'test_user',
++                    password = 'db_passwd',
++                    port = 1234,
++                    use_ssl = True,
++                    client_cert_action = NO_CLIENT_CERT,
++                   )
++
++options = parser.parse_args()
++
++if options.client and options.server:
+     print "can't be both client and server"
+     sys.exit(1)
+-if not (client or server):
++if not (options.client or options.server):
+     print "must be one of client or server"
+     sys.exit(1)
+ 
+ # Perform basic configuration and setup
+-if certdir is None:
+-    nss.nss_init_nodb()
++if options.use_ssl:
++    nss.nss_init(options.db_name)
+ else:
+-    nss.nss_init(certdir)
++    nss.nss_init_nodb()
+ 
+ ssl.set_domestic_policy()
+ nss.set_password_callback(password_callback)
+ 
+ # Run as a client or as a server
+-if client:
++if options.client:
+     print "starting as client"
+     Client()
+ 
+-if server:
++if options.server:
+     print "starting as server"
+     Server()
+ 
+@@ -458,4 +426,3 @@
+     nss.nss_shutdown()
+ except Exception, e:
+     print e
+-
+diff -N -u -r python-nss-0.14.0/doc/examples/verify_cert.py python-nss-0.14.1/doc/examples/verify_cert.py
+--- python-nss-0.14.0/doc/examples/verify_cert.py	2013-04-15 13:05:46.000000000 -0400
++++ python-nss-0.14.1/doc/examples/verify_cert.py	2013-10-08 13:04:51.000000000 -0400
+@@ -1,7 +1,7 @@
+ #!/usr/bin/python
+ 
++import argparse
+ import sys
+-import optparse
+ 
+ import nss.nss as nss
+ import nss.error as nss_error
+@@ -75,75 +75,74 @@
+     lines.extend(nss.make_line_fmt_tuples(level, msg))
+     lines.extend(obj.format_lines(level+1))
+     return nss.indented_format(lines)
+-    
++
+ 
+ #-------------------------------------------------------------------------------
+ 
+ def main():
+-    # Command line argument processing
+-    parser = optparse.OptionParser()
+-
+-    parser.set_defaults(dbdir = '/etc/pki/nssdb',
+-                        db_passwd = 'db_passwd',
+-                        input_format = 'pem',
+-                        check_sig = True,
+-                        print_cert = False,
+-                        with_log = True,
+-                        check_ca = True,
+-                        )
++    global options
+ 
+-    param_group = optparse.OptionGroup(parser, 'NSS Database',
+-                                       'Specify & control the NSS Database')
++    parser = argparse.ArgumentParser(description='certificate validation example')
+ 
+-    param_group.add_option('-d', '--dbdir', dest='dbdir',
+-                           help='NSS database directory, default="%default"')
+-    param_group.add_option('-P', '--db-passwd', dest='db_passwd',
+-                           help='NSS database password, default="%default"')
++    # === NSS Database Group ===
++    group = parser.add_argument_group('NSS Database',
++                                      'Specify & control the NSS Database')
++    group.add_argument('-d', '--db-name',
++                       help='NSS database name (e.g. "sql:pki")')
+ 
+-    parser.add_option_group(param_group)
++    group.add_argument('-P', '--db-passwd',
++                       help='NSS database password')
+ 
+-    param_group = optparse.OptionGroup(parser, 'Certificate',
+-                                       'Specify how the certificate is loaded')
++    # === Certificate Group ===
++    group = parser.add_argument_group('Certificate',
++                                      'Specify how the certificate is loaded')
+ 
+-    param_group.add_option('-f', '--file', dest='cert_filename',
+-                           help='read cert from file')
+-    param_group.add_option('--format', dest='input_format', choices=['pem', 'der'],
+-                           help='import format for certificate (der|pem) default="%default"')
+-    param_group.add_option('-n', '--nickname', dest='cert_nickname',
+-                           help='load cert from NSS database by looking it up under this nickname')
++    group.add_argument('-f', '--file', dest='cert_filename',
++                       help='read cert from file')
+ 
++    group.add_argument('-F', '--input-format', choices=['pem', 'der'],
++                       help='format of input cert')
+ 
+-    parser.add_option_group(param_group)
++    group.add_argument('-n', '--nickname', dest='cert_nickname',
++                       help='load cert from NSS database by looking it up under this nickname')
+ 
+-    param_group = optparse.OptionGroup(parser, 'Validation',
+-                                       'Control the validation')
++    # === Validation Group ===
++    group = parser.add_argument_group('Validation',
++                                      'Control the validation')
+ 
+-    param_group.add_option('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
+-                           help='may be specified multiple times, default="CheckAllUsages", may be one of: %s' % ', '.join(sorted(cert_usage_map.keys())))
+-    param_group.add_option('-c', '--check-sig', action='store_true', dest='check_sig',
+-                           help='check signature default=%default')
+-    param_group.add_option('-C', '--no-check-sig', action='store_false', dest='check_sig',
++    group.add_argument('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
++                           help='certificate usage flags, may be specified multiple times')
++    group.add_argument('-c', '--check-sig', action='store_true', dest='check_sig',
+                            help='check signature')
+-    param_group.add_option('-l', '--log', action='store_true', dest='with_log',
+-                           help='use verify log, default=%default')
+-    param_group.add_option('-L', '--no-log', action='store_false', dest='with_log',
+-                           help='use verify log, default=%default')
+-    param_group.add_option('-a', '--check-ca', action='store_true', dest='check_ca',
+-                           help='check if cert is CA, default=%default')
+-    param_group.add_option('-A', '--no-check-ca', action='store_false', dest='check_ca',
+-                           help='check if cert is CA, default=%default')
+-
+-    parser.add_option_group(param_group)
+-
+-    param_group = optparse.OptionGroup(parser, 'Miscellaneous',
+-                                       'Miscellaneous options')
++    group.add_argument('-C', '--no-check-sig', action='store_false', dest='check_sig',
++                           help='do not check signature')
++    group.add_argument('-l', '--log', action='store_true', dest='with_log',
++                           help='use verify log')
++    group.add_argument('-L', '--no-log', action='store_false', dest='with_log',
++                           help='do not use verify log')
++    group.add_argument('-a', '--check-ca', action='store_true', dest='check_ca',
++                           help='check if cert is CA')
++    group.add_argument('-A', '--no-check-ca', action='store_false', dest='check_ca',
++                           help='do not check if cert is CA')
++
++    # === Miscellaneous Group ===
++    group = parser.add_argument_group('Miscellaneous',
++                                      'Miscellaneous options')
+ 
+-    param_group.add_option('-p', '--print-cert', action='store_true', dest='print_cert',
+-                           help='print the certificate in a friendly fashion, default=%default')
++    group.add_argument('-p', '--print-cert', action='store_true', dest='print_cert',
++                       help='print the certificate in a friendly fashion')
+ 
+-    parser.add_option_group(param_group)
+ 
+-    options, args = parser.parse_args()
++    parser.set_defaults(db_name = 'sql:pki',
++                        db_passwd = 'db_passwd',
++                        input_format = 'pem',
++                        check_sig = True,
++                        with_log = True,
++                        check_ca = True,
++                        print_cert = False,
++                        )
++
++    options = parser.parse_args()
+ 
+     # Process the command line arguments
+ 
+@@ -175,9 +174,9 @@
+         return 1
+ 
+     # Initialize NSS.
+-    print indented_output('NSS Database', options.dbdir)
++    print indented_output('NSS Database', options.db_name)
+     print
+-    nss.nss_init(options.dbdir)
++    nss.nss_init(options.db_name)
+     certdb = nss.get_default_certdb()
+     nss.set_password_callback(password_callback)
+ 
+@@ -194,7 +193,7 @@
+         except Exception, e:
+             print e
+             print >>sys.stderr, 'Unable to load cert nickname "%s" from database "%s"' % \
+-                (options.cert_nickname, options.dbdir)
++                (options.cert_nickname, options.db_name)
+             return 1
+ 
+     # Dump the cert if the user wants to see it
+@@ -282,5 +281,3 @@
+ #-------------------------------------------------------------------------------
+ if __name__ == "__main__":
+     sys.exit(main())
+-
+-
+diff -N -u -r python-nss-0.14.0/doc/examples/verify_server.py python-nss-0.14.1/doc/examples/verify_server.py
+--- python-nss-0.14.0/doc/examples/verify_server.py	2013-04-15 13:05:46.000000000 -0400
++++ python-nss-0.14.1/doc/examples/verify_server.py	2013-10-08 13:00:37.000000000 -0400
+@@ -4,10 +4,10 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ 
++import argparse
++import getpass
+ import os
+ import sys
+-import getopt
+-import getpass
+ 
+ from nss.error import NSPRError
+ import nss.io as io
+@@ -16,11 +16,6 @@
+ 
+ # -----------------------------------------------------------------------------
+ 
+-# command line parameters, default them to something reasonable
+-#certdir = '/etc/httpd/alias'
+-certdir = '/etc/pki/nssdb'
+-hostname = 'www.verisign.com'
+-port = 443
+ timeout_secs = 3
+ 
+ request = '''\
+@@ -104,18 +99,18 @@
+     valid_addr = False
+     # Get the IP Address of our server
+     try:
+-        addr_info = io.AddrInfo(hostname)
++        addr_info = io.AddrInfo(options.hostname)
+     except:
+-        print "ERROR: could not resolve hostname \"%s\"" % hostname
++        print "ERROR: could not resolve hostname \"%s\"" % options.hostname
+         return
+ 
+     for net_addr in addr_info:
+-        net_addr.port = port
++        net_addr.port = options.port
+         sock = ssl.SSLSocket(net_addr.family)
+         # Set client SSL socket options
+         sock.set_ssl_option(ssl.SSL_SECURITY, True)
+         sock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
+-        sock.set_hostname(hostname)
++        sock.set_hostname(options.hostname)
+ 
+         # Provide a callback which notifies us when the SSL handshake is
+         # complete
+@@ -135,7 +130,7 @@
+             continue
+ 
+     if not valid_addr:
+-        print "ERROR: could not connect to \"%s\"" % hostname
++        print "ERROR: could not connect to \"%s\"" % options.hostname
+         return
+ 
+     try:
+@@ -158,48 +153,31 @@
+ 
+ # -----------------------------------------------------------------------------
+ 
+-usage_str = '''
+--d --certdir    certificate directory (default: %(certdir)s)
+--h --hostname   host to connect to (default: %(hostname)s)
+--p --port       host port (default: %(port)s)
+-''' % {
+-       'certdir'             : certdir,
+-       'hostname'            : hostname,
+-       'port'                : port,
+-       }
++parser = argparse.ArgumentParser(description='certificate verification example',
++                                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ 
+-def usage():
+-    print usage_str
++parser.add_argument('-d', '--db-name',
++                    help='NSS database name (e.g. "sql:pki")')
+ 
+-try:
+-    opts, args = getopt.getopt(sys.argv[1:], "Hd:h:p:",
+-                               ["help", "certdir=", "hostname=",
+-                                "port=",
+-                                ])
+-except getopt.GetoptError:
+-    # print help information and exit:
+-    usage()
+-    sys.exit(2)
+-
+-
+-for o, a in opts:
+-    if o in ("-d", "--certdir"):
+-        certdir = a
+-    if o in ("-h", "--hostname"):
+-        hostname = a
+-    if o in ("-p", "--port"):
+-        port = int(a)
+-    if o in ("-H", "--help"):
+-        usage()
+-        sys.exit()
++parser.add_argument('-H', '--hostname',
++                    help='host to connect to')
++
++parser.add_argument('-p', '--port', type=int,
++                    help='host port')
++
++parser.set_defaults(db_name = 'sql:pki',
++                    hostname = 'www.verisign.com',
++                    port = 443,
++                    )
++
++options = parser.parse_args()
+ 
+ # Perform basic configuration and setup
+ try:
+-    nss.nss_init(certdir)
++    nss.nss_init(options.db_name)
+     ssl.set_domestic_policy()
+ except Exception, e:
+     print >>sys.stderr, e.strerror
+     sys.exit(1)
+ 
+ client()
+-
+diff -N -u -r python-nss-0.14.0/src/__init__.py python-nss-0.14.1/src/__init__.py
+--- python-nss-0.14.0/src/__init__.py	2013-04-24 16:30:26.000000000 -0400
++++ python-nss-0.14.1/src/__init__.py	2013-10-08 14:38:28.000000000 -0400
+@@ -163,8 +163,8 @@
+ 
+ - Initialize NSS and indicate the certficate database (CertDB)::
+ 
+-    certdir = './pki'
+-    ssl.nssinit(certdir)
++    db_name = 'sql:pki'
++    ssl.nssinit(db_name)
+ 
+ - If you are implementing an SSL server call config_secure_server()
+   (see ssl_example.py)::
+@@ -244,7 +244,7 @@
+     future we can find a solution but the immediate goal of the NSS
+     Python binding was to expose NSS through Python, not necessarily
+     to solve the larger integration issue of Python run-time and NSPR
+-    run-time. 
++    run-time.
+ 
+     - NSPR would like to hide the underlying platform socket (in the
+       NSPR code this is called "osfd"). There are NSPR API's which
+@@ -312,5 +312,4 @@
+ To be added
+ 
+ """
+-__version__ = '0.14.0'
+-
++__version__ = '0.14.1'
+diff -N -u -r python-nss-0.14.0/test/run_tests python-nss-0.14.1/test/run_tests
+--- python-nss-0.14.0/test/run_tests	2013-04-30 11:03:54.000000000 -0400
++++ python-nss-0.14.1/test/run_tests	2013-10-08 12:57:56.000000000 -0400
+@@ -1,21 +1,13 @@
+ #!/usr/bin/python
+ 
+-import getopt
+-import sys
++import argparse
+ import os
++import sys
+ import unittest
+ from util import get_build_dir
+ 
+ #-------------------------------------------------------------------------------
+ 
+-prog_name = os.path.basename(sys.argv[0])
+-
+-config = {
+-    'in_tree'          : True,
+-}
+-
+-#-------------------------------------------------------------------------------
+-
+ def run_tests():
+ 
+     import setup_certs
+@@ -23,9 +15,11 @@
+     import test_cipher
+     import test_digest
+     import test_pkcs12
++    import test_misc
++    import test_ocsp
+     import test_client_server
+ 
+-    setup_certs.setup_certs()
++    setup_certs.setup_certs([])
+ 
+     loader = unittest.TestLoader()
+     runner = unittest.TextTestRunner()
+@@ -43,62 +37,19 @@
+ 
+ #-------------------------------------------------------------------------------
+ 
+-class Usage(Exception):
+-    def __init__(self, msg):
+-        self.msg = msg
+-
+-def usage():
+-    'Print command help.'
+-
+-    return '''\
+-%(prog_name)s [-i]
+-
+--h --help          print help
+--i --installed     runs the test using installed libraries
+-                   instead of "in tree" libraries
+-
+-Runs unit tests.
+-By default test is done "in tree".
+-
+-Examples:
+-
+-Run test using libraries built in this tree
+-%(prog_name)s
+-
+-Run post install test
+-%(prog_name)s -i
+-''' % {'prog_name' : prog_name,
+-      }
+-
+-#-------------------------------------------------------------------------------
++def main():
++    parser = argparse.ArgumentParser(description='run the units (installed or in tree)')
++    parser.add_argument('-i', '--installed', action='store_false', dest='in_tree',
++                        help='run tests using installed library')
++    parser.add_argument('-t', '--in-tree', action='store_true', dest='in_tree',
++                        help='run tests using devel tree')
+ 
+-def main(argv=None):
+-    if argv is None:
+-        argv = sys.argv
+-
+-    try:
+-        try:
+-            opts, args = getopt.getopt(argv[1:], 'hi',
+-                                       ['help', 'installed',])
+-        except getopt.GetoptError, e:
+-            raise Usage(e)
+-            return 2
+-
+-        for o, a in opts:
+-            if o in ('-h', '--help'):
+-                print >>sys.stdout, usage()
+-                return 0
+-            elif o in ('-i', '--installed'):
+-                config['in_tree'] = False
+-            else:
+-                raise Usage("command argument '%s' not handled, internal error" % o)
+-    except Usage, e:
+-        print >>sys.stderr, e.msg
+-        print >>sys.stderr, "for help use --help"
+-        return 2
++    parser.set_defaults(in_tree = False,
++                        )
+ 
++    options = parser.parse_args()
+ 
+-    if config['in_tree']:
++    if options.in_tree:
+         # Run the tests "in the tree"
+         # Rather than testing with installed versions run the test
+         # with the package built in this tree.
+diff -N -u -r python-nss-0.14.0/test/setup_certs.py python-nss-0.14.1/test/setup_certs.py
+--- python-nss-0.14.0/test/setup_certs.py	2013-04-18 12:28:05.000000000 -0400
++++ python-nss-0.14.1/test/setup_certs.py	2013-10-17 11:07:09.000000000 -0400
+@@ -1,345 +1,506 @@
+ #!/usr/bin/python
+ 
+-import traceback
+-import getopt
+-import sys
+-import os
+-import errno
++import argparse
++import atexit
+ import logging
+-import subprocess
++import os
+ import shutil
+-import shlex
+-import pty
+-import tty
+-import re
+-import time
+-
+-#-------------------------------------------------------------------------------
+-
+-__all__ = ["config", "setup_certs"]
+-
+-if __name__ == '__main__':
+-    prog_name = os.path.basename(sys.argv[0])
+-else:
+-    prog_name = 'setup_certs'
+-
+-serial_number = 0
+-hostname = os.uname()[1]
+-client_username = 'test_user'
+-
+-config = {
+-    'verbose'          : False,
+-    'debug'            : False,
+-    'logfile'          : 'setup_certs.log',
+-    'log_level'        : logging.WARN,
+-    'interactive'      : sys.stdout.isatty(),
+-    'dbdir'            : os.path.join(os.path.dirname(sys.argv[0]), 'pki'),
+-    'db_passwd'        : 'db_passwd',
+-    'noise_file'       : 'noise_file',
+-    'ca_subject'       : 'CN=Test CA',
+-    'ca_nickname'      : 'test_ca',
+-    'server_subject'   : 'CN=%s' % hostname,
+-    'server_nickname'  : 'test_server',
+-    'client_subject'   : 'CN=%s' % client_username,
+-    'client_nickname'  : client_username,
+-}
++import subprocess
++import sys
++from string import Template
++import tempfile
+ 
+ #-------------------------------------------------------------------------------
+ 
+ class CmdError(Exception):
+-    def __init__(self, cmd, exit_code, msg):
+-        self.cmd = cmd
+-        self.exit_code = exit_code
+-        self.msg = msg
++    def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None):
++        self.cmd_args = cmd_args
++        self.returncode = returncode
++        if message is None:
++            self.message = 'Failed error=%s, ' % (returncode)
++            if stderr:
++                self.message += '"%s", ' % stderr
++            self.message += 'args=%s' % (cmd_args)
++        else:
++            self.message = message
++        self.stdout = stdout
++        self.stderr = stderr
+ 
+     def __str__(self):
+-        return "Command \"%s\"\nFailed with exit code = %s\nOutput was:\n%s\n" % \
+-            (self.cmd, self.exit_code, self.msg)
++        return self.message
+ 
+-#-------------------------------------------------------------------------------
+ 
+-def next_serial():
+-    global serial_number
+-    serial_number += 1
+-    return serial_number
++def run_cmd(cmd_args, input=None):
++    logging.debug(' '.join(cmd_args))
++    try:
++        p = subprocess.Popen(cmd_args,
++                             stdin=subprocess.PIPE,
++                             stdout=subprocess.PIPE,
++                             stderr=subprocess.PIPE)
++        stdout, stderr = p.communicate(input)
++        returncode = p.returncode
++        if returncode != 0:
++            raise CmdError(cmd_args, returncode,
++                           'failed %s' % (', '.join(cmd_args)),
++                           stdout, stderr)
++        return stdout, stderr
++    except OSError as e:
++        raise CmdError(cmd_args, e.errno, stderr=str(e))
++
++def exit_handler(options):
++    logging.debug('in exit handler')
++
++    if options.passwd_filename is not None:
++        logging.debug('removing passwd_filename=%s', options.passwd_filename)
++        os.remove(options.passwd_filename)
++
++    if options.noise_filename is not None:
++        logging.debug('removing noise_filename=%s', options.noise_filename)
++        os.remove(options.noise_filename)
++
++def write_serial(options, serial_number):
++    with open(options.serial_file, 'w') as f:
++        f.write('%x\n' % serial_number)
++
++
++def read_serial(options):
++    if not os.path.exists(options.serial_file):
++        write_serial(options, options.serial_number)
+ 
+-def create_noise_file():
+-    """
+-    Generate a noise file to be used when creating a key
+-    """
+-    if os.path.exists(config['noise_file']):
+-        os.remove(config['noise_file'])
+-
+-    f = open(config['noise_file'], "w")
+-    f.write(os.urandom(40))
+-    f.close()
++    with open(options.serial_file) as f:
++        serial_number = int(f.readline(), 16)
++    return serial_number
+ 
+-    return
+ 
+-def run_cmd(cmd, input=None):
+-    logging.debug("running command: %s", cmd)
++def init_noise_file(options):
++    '''Generate a noise file to be used when creating a key
+ 
+-    if input is None:
+-        stdin = None
+-    else:
+-        stdin = subprocess.PIPE
++    We create a temporary file on first use and continue to use
++    the same temporary file for the duration of this process.
++    Each time this function is called it writes new random data
++    into the file.
++    '''
++    random_data = os.urandom(40)
+ 
+-    p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+-    stdout, stderr = p.communicate(input)
+-    status = p.returncode
+-    if config['verbose']:
+-        logging.debug("cmd status = %s", status)
+-        logging.debug("cmd stdout = %s", stdout)
+-        logging.debug("cmd stderr = %s", stderr)
+-    return status, stdout, stderr
+-
+-def run_cmd_with_prompts(cmd, prompts):
+-    logging.debug('running command: %s', cmd)
+-
+-    argv = shlex.split(cmd)
+-
+-    pid, master_fd = pty.fork()
+-    if pid == 0:
+-        os.execlp(argv[0], *argv)
+-
+-    time.sleep(0.1)            # FIXME: why is this necessary?
+-    output = ''
+-    search_position = 0
+-    cur_prompt = 0
+-    if cur_prompt < len(prompts):
+-        prompt_re = re.compile(prompts[cur_prompt][0])
+-        response = prompts[cur_prompt][1]
+-        cur_prompt += 1
++    if options.noise_filename is None:
++        fd, options.noise_filename = tempfile.mkstemp()
++        os.write(fd, random_data)
++        os.close(fd)
+     else:
+-        prompt_re = None
+-        response = None
+-
+-    while True:
+-        try:
+-            new_data = os.read(master_fd, 1024)
+-        except OSError, e:
+-            if e.errno == errno.EIO: # process exited
+-                break
+-            else:
+-                raise
+-        if len(new_data) == 0:
+-            break               # EOF
+-        output += new_data
+-        logging.debug('output="%s"', output[search_position:]);
+-        if prompt_re is not None:
+-            logging.debug('search pattern = "%s"', prompt_re.pattern)
+-            match = prompt_re.search(output, search_position)
+-            if match:
+-                search_position = match.end()
+-                parsed = output[match.start() : match.end()]
+-                logging.debug('found prompt: "%s"', parsed)
+-                logging.debug('writing response: "%s"', response)
+-                os.write(master_fd, response)
+-
+-                if cur_prompt < len(prompts):
+-                    prompt_re = re.compile(prompts[cur_prompt][0])
+-                    response = prompts[cur_prompt][1]
+-                    cur_prompt += 1
+-                else:
+-                    prompt_re = None
+-                    response = None
+-
+-
+-    exit_value = os.waitpid(pid, 0)[1]
+-    exit_signal = exit_value & 0xFF
+-    exit_code = exit_value >> 8
+-    #logging.debug('output="%s"' % output)
+-    logging.debug('cmd signal=%s, exit_code=%s' % (exit_signal, exit_code))
+-
+-    return exit_code, output
++        with open(options.noise_filename, 'w') as f:
++            f.write(random_data)
++    return
+ 
++def create_passwd_file(options):
++    fd, options.passwd_filename = tempfile.mkstemp()
++    os.write(fd, options.db_passwd)
++    os.close(fd)
+ 
+-#-------------------------------------------------------------------------------
+ 
+-def setup_certs():
+-    print 'setting up certs ...'
+-
+-    if os.path.exists(config['dbdir']):
+-       shutil.rmtree(config['dbdir'])
+-    os.makedirs(config['dbdir'])
++def db_has_cert(options, nickname):
++    cmd_args = ['/usr/bin/certutil',
++                '-d', options.db_name,
++                '-L',
++                '-n', nickname]
+ 
+     try:
++        run_cmd(cmd_args)
++    except CmdError as e:
++        if e.returncode == 255 and 'not found' in e.stderr:
++            return False
++        else:
++            raise
++    return True
++
++def format_cert(options, nickname):
++    cmd_args = ['/usr/bin/certutil',
++                '-L',                          # OPERATION: list
++                '-d', options.db_name,         # NSS database
++                '-f', options.passwd_filename, # database password in file
++                '-n', nickname,                # nickname of cert to list
++                ]
+ 
+-        create_noise_file()
+-
+-        # 1. Create the database
+-        cmd = 'certutil -N -d %(dbdir)s' % config
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-            [('Enter new password:\s*', config['db_passwd'] + '\n'),
+-             ('Re-enter password:\s*',  config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 2. Create a root CA certificate
+-        config['serial_number'] = next_serial()
+-        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
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-            [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 3. Create a server certificate and sign it.
+-        config['serial_number'] = next_serial()
+-        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
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-            [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 4. Create a client certificate and sign it.
+-        config['serial_number'] = next_serial()
+-        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
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-                                                 [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 5. Import public root CA's
+-        cmd = 'modutil -dbdir %(dbdir)s -add ca_certs -libfile libnssckbi.so' % config
+-        exit_code, stdout, stderr = run_cmd(cmd)
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 6. Create a sub CA certificate
+-        config['serial_number'] = next_serial()
+-        config['subca_subject'] = 'CN=subca'
+-        config['subca_nickname'] = 'subca'
+-        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
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-            [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-        # 7. Create a server certificate and sign it with the subca.
+-        config['serial_number'] = next_serial()
+-        config['server_subject'] = config['server_subject'] + "_" + config['subca_nickname']
+-        config['server_nickname'] = config['server_nickname'] + "_" + config['subca_nickname']
+-        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
+-        exit_code, output = run_cmd_with_prompts(cmd,
+-            [('Enter Password or Pin for "NSS Certificate DB":\s*', config['db_passwd'] + '\n')])
+-        if exit_code != 0:
+-            raise CmdError(cmd, exit_code, output)
+-
+-    finally:
+-        if os.path.exists(config['noise_file']):
+-            os.remove(config['noise_file'])
+-
+-    logging.info('certifcate database password="%(db_passwd)s"', config)
+-    logging.info('CA nickname="%(ca_nickname)s", CA subject="%(ca_subject)s"', config)
+-    logging.info('server nickname="%(server_nickname)s", server subject="%(server_subject)s"', config)
+-    logging.info('client nickname="%(client_nickname)s", client subject="%(client_subject)s"', config)
++    stdout, stderr = run_cmd(cmd_args)
++    return stdout
+ 
+ #-------------------------------------------------------------------------------
+ 
+-class Usage(Exception):
+-    def __init__(self, msg):
+-        self.msg = msg
++def create_database(options):
++    if os.path.exists(options.db_dir) and not os.path.isdir(options.db_dir):
++        raise ValueError('db_dir "%s" exists but is not a directory' % options.db_dir)
++
++    # Create resources
++    create_passwd_file(options)
++
++    if options.clean:
++        logging.info('Creating clean database directory: "%s"', options.db_dir)
++
++        if os.path.exists(options.db_dir):
++            shutil.rmtree(options.db_dir)
++        os.makedirs(options.db_dir)
++
++        cmd_args = ['/usr/bin/certutil',
++                    '-N',                          # OPERATION: create database
++                    '-d', options.db_name,         # NSS database
++                    '-f', options.passwd_filename, # database password in file
++                    ]
+ 
+-def usage():
+-    '''
+-    Print command help.
+-    '''
++        stdout, stderr = run_cmd(cmd_args)
++    else:
++        logging.info('Using existing database directory: "%s"', options.db_dir)
++
++def create_ca_cert(options):
++    serial_number = read_serial(options)
++    init_noise_file(options)
++
++    logging.info('creating ca cert: subject="%s", nickname="%s"',
++                 options.ca_subject, options.ca_nickname)
++
++    cmd_args = ['/usr/bin/certutil',
++                '-S',                            # OPERATION: create signed cert
++                '-x',                            # self-sign the cert
++                '-d', options.db_name,           # NSS database
++                '-f', options.passwd_filename,   # database password in file
++                '-n', options.ca_nickname,       # nickname of cert being created
++                '-s', options.ca_subject,        # subject of cert being created
++                '-g', str(options.key_size),     # keysize
++                '-t', 'CT,,CT',                  # trust
++                '-1',                            # add key usage extension
++                '-2',                            # add basic contraints extension
++                '-5',                            # add certificate type extension
++                '-m', str(serial_number),        # cert serial number
++                '-v', str(options.valid_months), # validity in months
++                '-z', options.noise_filename,    # noise file random seed
++                ]
++
++    # Provide input for extension creation prompting
++    input = ''
++
++    # >> Key Usage extension <<
++    # 0 - Digital Signature
++    # 1 - Non-repudiation
++    # 2 - Key encipherment
++    # 3 - Data encipherment
++    # 4 - Key agreement
++    # 5 - Cert signing key
++    # 6 - CRL signing key
++    # Other to finish
++    input += '0\n1\n5\n100\n'
++    # Is this a critical extension [y/N]?
++    input += 'y\n'
++
++    # >> Basic Constraints extension <<
++    # Is this a CA certificate [y/N]?
++    input += 'y\n'
++    # Enter the path length constraint, enter to skip [<0 for unlimited path]: > 2
++    input += '%d\n' % options.ca_path_len
++    # Is this a critical extension [y/N]?
++    input += 'y\n'
++
++    # >> NS Cert Type extension <<
++    # 0 - SSL Client
++    # 1 - SSL Server
++    # 2 - S/MIME
++    # 3 - Object Signing
++    # 4 - Reserved for future use
++    # 5 - SSL CA
++    # 6 - S/MIME CA
++    # 7 - Object Signing CA
++    # Other to finish
++    input += '5\n6\n7\n100\n'
++    # Is this a critical extension [y/N]?
++    input += 'n\n'
++
++    stdout, stderr = run_cmd(cmd_args, input)
++    write_serial(options, serial_number + 1)
++
++    return options.ca_nickname
++
++def create_server_cert(options):
++    serial_number = read_serial(options)
++    init_noise_file(options)
++
++    logging.info('creating server cert: subject="%s", nickname="%s"',
++                 options.server_subject, options.server_nickname)
++
++    cmd_args = ['/usr/bin/certutil',
++                '-S',                            # OPERATION: create signed cert
++                '-d', options.db_name,           # NSS database
++                '-f', options.passwd_filename,   # database password in file
++                '-c', options.ca_nickname,       # nickname of CA used to sign this cert
++                '-n', options.server_nickname,   # nickname of cert being created
++                '-s', options.server_subject,    # subject of cert being created
++                '-g', str(options.key_size),     # keysize
++                '-t', 'u,u,u',                   # trust
++                '-5',                            # add certificate type extensionn
++                '-m', str(serial_number),        # cert serial number
++                '-v', str(options.valid_months), # validity in months
++                '-z', options.noise_filename,    # noise file random seed
++                ]
++
++    # Provide input for extension creation prompting
++    input = ''
++
++    # >> NS Cert Type extension <<
++    # 0 - SSL Client
++    # 1 - SSL Server
++    # 2 - S/MIME
++    # 3 - Object Signing
++    # 4 - Reserved for future use
++    # 5 - SSL CA
++    # 6 - S/MIME CA
++    # 7 - Object Signing CA
++    # Other to finish
++    input += '1\n100\n'
++    # Is this a critical extension [y/N]?
++    input += 'n\n'
++
++    stdout, stderr = run_cmd(cmd_args, input)
++    write_serial(options, serial_number + 1)
++
++    return options.server_nickname
++
++def create_client_cert(options):
++    serial_number = read_serial(options)
++    init_noise_file(options)
++
++    logging.info('creating client cert: subject="%s", nickname="%s"',
++                 options.client_subject, options.client_nickname)
++
++    cmd_args = ['/usr/bin/certutil',
++                '-S',                            # OPERATION: create signed cert
++                '-d', options.db_name,           # NSS database
++                '-f', options.passwd_filename,   # database password in file
++                '-c', options.ca_nickname,       # nickname of CA used to sign this cert
++                '-n', options.client_nickname,   # nickname of cert being created
++                '-s', options.client_subject,    # subject of cert being created
++                '-g', str(options.key_size),     # keysize
++                '-t', 'u,u,u',                   # trust
++                '-5',                            # add certificate type extensionn
++                '-m', str(serial_number),        # cert serial number
++                '-v', str(options.valid_months), # validity in months
++                '-z', options.noise_filename,    # noise file random seed
++                ]
++
++    # Provide input for extension creation prompting
++    input = ''
++
++    # >> NS Cert Type extension <<
++    # 0 - SSL Client
++    # 1 - SSL Server
++    # 2 - S/MIME
++    # 3 - Object Signing
++    # 4 - Reserved for future use
++    # 5 - SSL CA
++    # 6 - S/MIME CA
++    # 7 - Object Signing CA
++    # Other to finish
++    input += '0\n100\n'
++    # Is this a critical extension [y/N]?
++    input += 'n\n'
++
++    stdout, stderr = run_cmd(cmd_args, input)
++    write_serial(options, serial_number + 1)
++
++    return options.client_nickname
++
++def add_trusted_certs(options):
++    name = 'ca_certs'
++    module = 'libnssckbi.so'
++    logging.info('adding system trusted certs: name="%s" module="%s"',
++                 name, module)
++
++    cmd_args = ['/usr/bin/modutil',
++                '-dbdir', options.db_name, # NSS database
++                '-add', name,              # module name
++                '-libfile', module,        # module
++                ]
+ 
+-    return '''\
+--h --help               print help
+--l --log-level level    set the logging level, may be one of:
+-                        debug, info, warn, error, critical
+--L --logfile filename   log to this file, empty string disables logging to a file
+--v --verbose            be chatty
+--D --debug              show run information
+--w --password           set the certificate database password
+--d --dbdir              set the datbase directory
+--s --server-subject     set the server's subject
+-
+-Examples:
+-
+-%(prog_name)s -m 10
+-''' % {'prog_name' : prog_name,
+-      }
++    run_cmd(cmd_args)
++    return name
+ 
+ #-------------------------------------------------------------------------------
+ 
+-def main(argv=None):
+-    if argv is None:
+-        argv = sys.argv
++def setup_certs(args):
+ 
+-    try:
+-        try:
+-            opts, args = getopt.getopt(argv[1:], 'hl:L:vDw:d:s:',
+-                                       ['help', 'logfile=', 'verbose', 'debug',
+-                                        'password', 'dbdir', 'server-subject'])
+-        except getopt.GetoptError, e:
+-            raise Usage(e)
+-            return 2
+-
+-        for o, a in opts:
+-            if o in ('-h', '--help'):
+-                print >>sys.stdout, usage()
+-                return 0
+-            elif o in ('-L', '--logfile'):
+-                if not a:
+-                    config['logfile'] = None
+-                else:
+-                    config['logfile'] = a
+-            elif o in ('-l', '--log-level'):
+-                if a.upper() in logging._levelNames:
+-                    config['log_level'] = logging._levelNames[a.upper()]
+-                else:
+-                    print >>sys.stderr, "ERROR: unknown log-level '%s'" % a
+-            elif o in ('-v', '--verbose'):
+-                config['verbose'] = True
+-            elif o in ('-D', '--debug'):
+-                config['debug'] = True
+-            elif o in ('-w', '--password'):
+-                config['db_passwd'] = a
+-            elif o in ('-d', '--dbdir'):
+-                config['dbdir'] = a
+-            elif o in ('-s', '--server-subject'):
+-                config['server_subject'] = 'CN=%s' % a
+-            else:
+-                raise Usage("command argument '%s' not handled, internal error" % o)
+-    except Usage, e:
+-        print >>sys.stderr, e.msg
+-        print >>sys.stderr, "for help use --help"
+-        return 2
+-
+-    if config['verbose']:
+-        config['log_level'] = logging.INFO
+-    if config['debug']:
+-        config['log_level'] = logging.DEBUG
++    # --- cmd ---
++    parser = argparse.ArgumentParser(description='create certs for testing',
++                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
++
++    parser.add_argument('--verbose', action='store_true',
++                        help='provide info level messages')
++
++    parser.add_argument('--debug', action='store_true',
++                        help='provide debug level messages')
++
++    parser.add_argument('--quiet', action='store_true',
++                        help='do not display any messages')
++
++    parser.add_argument('--show-certs', action='store_true',
++                        help='show the certificate details')
++
++    parser.add_argument('--no-clean', action='store_false', dest='clean',
++                        help='do not remove existing db_dir')
++
++    parser.add_argument('--no-trusted-certs', dest='add_trusted_certs', action='store_false',
++                        help='do not add trusted certs')
++
++    parser.add_argument('--hostname',
++                        help='hostname used in cert subjects')
++
++    parser.add_argument('--db-type',
++                        choices=['sql', ''],
++                        help='NSS database type')
++
++    parser.add_argument('--db-dir',
++                        help='NSS database directory')
++
++    parser.add_argument('--db-passwd',
++                        help='NSS database password')
++
++    parser.add_argument('--ca-subject',
++                        help='CA certificate subject')
++
++    parser.add_argument('--ca-nickname',
++                        help='CA certificate nickname')
++
++    parser.add_argument('--server-subject',
++                        help='server certificate subject')
++
++    parser.add_argument('--server-nickname',
++                        help='server certificate nickname')
++
++    parser.add_argument('--client-username',
++                        help='client user name, used in client cert subject')
++
++    parser.add_argument('--client-subject',
++                        help='client certificate subject')
++
++    parser.add_argument('--client-nickname',
++                        help='client certificate nickname')
++
++    parser.add_argument('--serial-number', type=int,
++                        help='starting serial number for certificates')
++
++    parser.add_argument('--valid-months', dest='valid_months', type=int,
++                        help='validity period in months')
++    parser.add_argument('--path-len', dest='ca_path_len', type=int,
++                        help='basic constraints path length')
++    parser.add_argument('--key-type', dest='key_type',
++                        help='key type, either rsa or dsa')
++    parser.add_argument('--key-size', dest='key_size',
++                        help='number of bits in key (must be multiple of 8)')
++    parser.add_argument('--serial-file', dest='serial_file',
++                        help='name of file used to track next serial number')
++
++    parser.set_defaults(verbose = False,
++                        debug = False,
++                        quiet = False,
++                        show_certs = False,
++                        clean = True,
++                        add_trusted_certs = True,
++                        hostname = os.uname()[1],
++                        db_type = 'sql',
++                        db_dir = 'pki',
++                        db_passwd = 'db_passwd',
++                        ca_subject = 'CN=Test CA',
++                        ca_nickname = 'test_ca',
++                        server_subject =  'CN=${hostname}',
++                        server_nickname = 'test_server',
++                        client_username = 'test_user',
++                        client_subject = 'CN=${client_username}',
++                        client_nickname = '${client_username}',
++                        serial_number = 1,
++                        key_type = 'rsa',
++                        key_size = 1024,
++                        valid_months = 12,
++                        ca_path_len = 2,
++                        serial_file = '${db_dir}/serial',
++                        )
++
++
++    options = parser.parse_args(args)
++
++    # Do substitutions on option values.
++    # This is ugly because argparse does not expose an API which permits iterating over
++    # the contents of options nor a way to get the options as a dict, ugh :-(
++    # So we access options.__dict__ directly.
++    for key in options.__dict__.keys():
++        # Assume options never begin with underscore
++        if key.startswith('_'):
++            continue
++        value = getattr(options, key)
++        # Can't substitue on non-string values
++        if not isinstance(value, basestring):
++            continue
++        # Don't bother trying to substitute if $ substitution character isn't present
++        if '$' not in value:
++            continue
++        setattr(options, key, Template(value).substitute(options.__dict__))
++
++    # Set up logging
++    log_level = logging.INFO
++    if options.quiet:
++        log_level = logging.ERROR
++    if options.verbose:
++        log_level = logging.INFO
++    if options.debug:
++        log_level = logging.DEBUG
+ 
+     # Initialize logging
+-    logging.basicConfig(level=config['log_level'],
+-                        format='%(asctime)s %(levelname)-8s %(message)s',
+-                        datefmt='%m-%d %H:%M',
+-                        filename=config['logfile'],
+-                        filemode='a')
+-
+-    if config['interactive']:
+-        # Create a seperate logger for the console
+-        console_logger = logging.StreamHandler()
+-        console_logger.setLevel(config['log_level'])
+-        # set a format which is simpler for console use
+-        formatter = logging.Formatter('%(message)s')
+-        console_logger.setFormatter(formatter)
+-        # add the handler to the root logger
+-        logging.getLogger('').addHandler(console_logger)
++    logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s')
++    logger = logging.getLogger()
++
++    # Synthesize some useful options derived from specified options
++    if options.db_type == '':
++        options.db_name = options.db_dir
++    else:
++        options.db_name = '%s:%s' % (options.db_type, options.db_dir)
++    options.passwd_filename = None
++    options.noise_filename = None
++
++    # Set function to clean up on exit, bind fuction with options
++    def exit_handler_with_options():
++        exit_handler(options)
++    atexit.register(exit_handler_with_options)
++
++    cert_nicknames = []
+ 
+     try:
+-        setup_certs()
+-    except Exception, e:
+-        logging.error(traceback.format_exc())
+-        logging.error(str(e))
++        create_database(options)
++        cert_nicknames.append(create_ca_cert(options))
++        cert_nicknames.append(create_server_cert(options))
++        cert_nicknames.append(create_client_cert(options))
++        if options.add_trusted_certs:
++            add_trusted_certs(options)
++    except CmdError as e:
++        logging.error(e.message)
++        logging.error(e.stderr)
+         return 1
+ 
++    if options.show_certs:
++        if logger.getEffectiveLevel() > logging.INFO:
++            logger.setLevel(logging.INFO)
++        for nickname in cert_nicknames:
++            logging.info('Certificate nickname "%s"\n%s',
++                         nickname, format_cert(options, nickname))
++
++    logging.info('---------- Summary ----------')
++    logging.info('NSS database name="%s", password="%s"',
++                 options.db_name, options.db_passwd)
++    logging.info('CA nickname="%s", CA subject="%s"',
++                 options.ca_nickname, options.ca_subject)
++    logging.info('server nickname="%s", server subject="%s"',
++                 options.server_nickname, options.server_subject)
++    logging.info('client nickname="%s", client subject="%s"',
++                 options.client_nickname, options.client_subject)
++
+     return 0
+ 
+ #-------------------------------------------------------------------------------
+ 
++def main():
++    return setup_certs(None)
++
+ if __name__ == '__main__':
+     sys.exit(main())
+diff -N -u -r python-nss-0.14.0/test/test_client_server.py python-nss-0.14.1/test/test_client_server.py
+--- python-nss-0.14.0/test/test_client_server.py	2013-04-30 13:00:23.000000000 -0400
++++ python-nss-0.14.1/test/test_client_server.py	2013-10-08 09:35:53.000000000 -0400
+@@ -25,13 +25,12 @@
+ password = 'db_passwd'
+ use_ssl = True
+ client_cert_action = NO_CLIENT_CERT
+-certdir = os.path.join(os.path.dirname(sys.argv[0]), 'pki')
++db_name = 'sql:pki'
+ hostname = os.uname()[1]
+ server_nickname = 'test_server'
+ client_nickname = 'test_user'
+ port = 1234
+ timeout_secs = 10
+-family = io.PR_AF_INET
+ sleep_time = 5
+ 
+ 
+@@ -142,7 +141,6 @@
+         if info: print "client: using SSL"
+         ssl.set_domestic_policy()
+ 
+-    valid_addr = False
+     # Get the IP Address of our server
+     try:
+         addr_info = io.AddrInfo(hostname)
+@@ -151,8 +149,6 @@
+         return
+ 
+     for net_addr in addr_info:
+-        if family != io.PR_AF_UNSPEC:
+-            if net_addr.family != family: continue
+         net_addr.port = port
+ 
+         if use_ssl:
+@@ -180,26 +176,21 @@
+             if verbose: print "client trying connection to: %s" % (net_addr)
+             sock.connect(net_addr, timeout=io.seconds_to_interval(timeout_secs))
+             if verbose: print "client connected to: %s" % (net_addr)
+-            valid_addr = True
+             break
+         except Exception, e:
+             sock.close()
+             print >>sys.stderr, "client: connection to: %s failed (%s)" % (net_addr, e)
+ 
+-    if not valid_addr:
+-        print >>sys.stderr, "Could not establish valid address for \"%s\" in family %s" % \
+-        (hostname, io.addr_family_name(family))
+-        return
+-
+     # Talk to the server
+     try:
+         if info: print "client: sending \"%s\"" % (request)
+-        sock.send(request)
+-        buf = sock.recv(1024)
++        sock.send(request + '\n') # newline is protocol record separator
++        buf = sock.readline()
+         if not buf:
+             print >>sys.stderr, "client: lost connection"
+             sock.close()
+             return
++        buf = buf.rstrip()        # remove newline record separator
+         if info: print "client: received \"%s\"" % (buf)
+     except Exception, e:
+         print >>sys.stderr, "client: %s" % e
+@@ -228,15 +219,11 @@
+ # -----------------------------------------------------------------------------
+ 
+ def server():
+-    global family
+-
+     if verbose: print "starting server:"
+ 
+     # Initialize
+     # Setup an IP Address to listen on any of our interfaces
+-    if family == io.PR_AF_UNSPEC:
+-        family = io.PR_AF_INET
+-    net_addr = io.NetworkAddress(io.PR_IpAddrAny, port, family)
++    net_addr = io.NetworkAddress(io.PR_IpAddrAny, port)
+ 
+     if use_ssl:
+         if info: print "server: using SSL"
+@@ -290,15 +277,16 @@
+         while True:
+             try:
+                 # Handle the client connection
+-                buf = client_sock.recv(1024)
++                buf = client_sock.readline()   # newline is protocol record separator
+                 if not buf:
+                     print >>sys.stderr, "server: lost lost connection to %s" % (client_addr)
+                     break
++                buf = buf.rstrip()             # remove newline record separator
+ 
+                 if info: print "server: received \"%s\"" % (buf)
+-                reply = "{%s}" % buf # echo
++                reply = "{%s}" % buf           # echo embedded inside braces
+                 if info: print "server: sending \"%s\"" % (reply)
+-                client_sock.send(reply) # echo
++                client_sock.send(reply + '\n') # send echo with record separator
+ 
+                 time.sleep(sleep_time)
+                 client_sock.shutdown()
+@@ -320,7 +308,7 @@
+ def run_server():
+     pid = os.fork()
+     if pid == 0:
+-        nss.nss_init(certdir)
++        nss.nss_init(db_name)
+         server()
+         nss.nss_shutdown()
+     time.sleep(sleep_time)
+@@ -348,7 +336,7 @@
+ 
+     def test_ssl(self):
+         request = "foo"
+-        nss.nss_init(certdir)
++        nss.nss_init(db_name)
+         reply = client(request)
+         nss.nss_shutdown()
+         self.assertEqual("{%s}" % request, reply)
+diff -N -u -r python-nss-0.14.0/test/test_ocsp.py python-nss-0.14.1/test/test_ocsp.py
+--- python-nss-0.14.0/test/test_ocsp.py	2013-04-24 12:36:07.000000000 -0400
++++ python-nss-0.14.1/test/test_ocsp.py	2013-10-08 09:09:18.000000000 -0400
+@@ -7,7 +7,7 @@
+ import nss.nss as nss
+ from nss.error import NSPRError
+ 
+-certdir = 'pki'
++db_name = 'sql:pki'
+ 
+ #-------------------------------------------------------------------------------
+ 
+@@ -16,7 +16,7 @@
+ 
+ class TestAPI(unittest.TestCase):
+     def setUp(self):
+-        nss.nss_init_read_write(certdir)
++        nss.nss_init_read_write(db_name)
+         self.certdb = nss.get_default_certdb()
+ 
+     def tearDown(self):
+diff -N -u -r python-nss-0.14.0/test/test_pkcs12.py python-nss-0.14.1/test/test_pkcs12.py
+--- python-nss-0.14.0/test/test_pkcs12.py	2013-04-15 13:05:46.000000000 -0400
++++ python-nss-0.14.1/test/test_pkcs12.py	2013-10-17 10:29:09.000000000 -0400
+@@ -2,6 +2,7 @@
+ 
+ import sys
+ import os
++import re
+ import subprocess
+ import shlex
+ import unittest
+@@ -13,30 +14,55 @@
+ #-------------------------------------------------------------------------------
+ 
+ verbose = False
+-certdir = 'pki'
++db_name = 'sql:pki'
+ db_passwd = 'db_passwd'
+-pkcs12_file_password = 'pk12_passwd'
++pk12_passwd = 'pk12_passwd'
+ 
+-read_nickname = 'test_user'
+-read_pkcs12_file = '%s.p12' % read_nickname
+-
+-write_export_file = False
+-export_nickname = 'test_server'
++cert_nickname = 'test_user'
++pk12_filename = '%s.p12' % cert_nickname
++exported_pk12_filename = 'exported_%s' % pk12_filename
+ 
+ #-------------------------------------------------------------------------------
+ 
+-def run_cmd(cmd):
+-    if verbose: print "running command: %s" % cmd
+-
+-    args = shlex.split(cmd)
+-    subprocess.check_call(args, stdout=subprocess.PIPE)
++class CmdError(Exception):
++    def __init__(self, cmd_args, returncode, message=None, stdout=None, stderr=None):
++        self.cmd_args = cmd_args
++        self.returncode = returncode
++        if message is None:
++            self.message = 'Failed error=%s, ' % (returncode)
++            if stderr:
++                self.message += '"%s", ' % stderr
++            self.message += 'args=%s' % (cmd_args)
++        else:
++            self.message = message
++        self.stdout = stdout
++        self.stderr = stderr
++
++    def __str__(self):
++        return self.message
++
++
++def run_cmd(cmd_args, input=None):
++    try:
++        p = subprocess.Popen(cmd_args,
++                             stdin=subprocess.PIPE,
++                             stdout=subprocess.PIPE,
++                             stderr=subprocess.PIPE)
++        stdout, stderr = p.communicate(input)
++        returncode = p.returncode
++        if returncode != 0:
++            raise CmdError(cmd_args, returncode,
++                           'failed %s' % (', '.join(cmd_args)),
++                           stdout, stderr)
++        return stdout, stderr
++    except OSError as e:
++        raise CmdError(cmd_args, e.errno, stderr=str(e))
+ 
+ #-------------------------------------------------------------------------------
+ 
+ def password_callback(slot, retry):
+     return db_passwd
+ 
+-#-------------------------------------------------------------------------------
+ 
+ def nickname_collision_callback(old_nickname, cert):
+     cancel = False
+@@ -44,6 +70,51 @@
+     return new_nickname, cancel
+ 
+ 
++def get_cert_der_from_db(nickname):
++    cmd_args = ['/usr/bin/certutil',
++                '-d', db_name,
++                '-L',
++                '-n', nickname]
++
++    try:
++        stdout, stderr = run_cmd(cmd_args)
++    except CmdError as e:
++        if e.returncode == 255 and 'not found' in e.stderr:
++            return None
++        else:
++            raise
++    return stdout
++
++def delete_cert_from_db(nickname):
++    cmd_args = ['/usr/bin/certutil',
++                '-d', db_name,
++                '-D',
++                '-n', nickname]
++
++    run_cmd(cmd_args)
++
++def create_pk12(nickname, filename):
++    cmd_args = ['/usr/bin/pk12util',
++                '-o', filename,
++                '-n', nickname,
++                '-d', db_name,
++                '-K', db_passwd,
++                '-W', pk12_passwd]
++    run_cmd(cmd_args)
++
++def list_pk12(filename):
++    cmd_args = ['/usr/bin/pk12util',
++                '-l', filename,
++                '-W', pk12_passwd]
++    stdout, stderr = run_cmd(cmd_args)
++    return stdout
++
++def strip_key_from_pk12_listing(text):
++    match = re.search(r'^Certificate:$', text, re.MULTILINE)
++    if not match:
++        raise ValueError('Could not file Key section in pk12 listing')
++    return text[match.start(0):]
++
+ #-------------------------------------------------------------------------------
+ 
+ def load_tests(loader, tests, pattern):
+@@ -59,22 +130,23 @@
+ 
+ class TestPKCS12Decoder(unittest.TestCase):
+     def setUp(self):
+-        nss.nss_init_read_write(certdir)
++        nss.nss_init_read_write(db_name)
+         nss.set_password_callback(password_callback)
+         nss.pkcs12_set_nickname_collision_callback(nickname_collision_callback)
+         nss.pkcs12_enable_all_ciphers()
++        self.cert_der = get_cert_der_from_db(cert_nickname)
++        if self.cert_der is None:
++            raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
+ 
+     def tearDown(self):
+         nss.nss_shutdown()
+ 
+     def test_read(self):
+         if verbose: print "test_read"
+-        cmd='pk12util -o %s -n %s -d pki -K %s -W %s' % \
+-            (read_pkcs12_file, read_nickname, db_passwd, pkcs12_file_password)
+-        run_cmd(cmd)
++        create_pk12(cert_nickname, pk12_filename)
+ 
+         slot = nss.get_internal_key_slot()
+-        pkcs12 = nss.PKCS12Decoder(read_pkcs12_file, pkcs12_file_password, slot)
++        pkcs12 = nss.PKCS12Decoder(pk12_filename, pk12_passwd, slot)
+ 
+         self.assertEqual(len(pkcs12), 3)
+         cert_bag_count = 0
+@@ -102,33 +174,43 @@
+ 
+     def test_import(self):
+         if verbose: print "test_import"
+-        cmd='certutil -d pki -D -n %s' % (read_nickname)
+-        run_cmd(cmd)
++        delete_cert_from_db(cert_nickname)
++        self.assertEqual(get_cert_der_from_db(cert_nickname), None)
+ 
+         slot = nss.get_internal_key_slot()
+-        pkcs12 = nss.PKCS12Decoder(read_pkcs12_file, pkcs12_file_password, slot)
++        pkcs12 = nss.PKCS12Decoder(pk12_filename, pk12_passwd, slot)
+         slot.authenticate()
+         pkcs12.database_import()
++        cert_der = get_cert_der_from_db(cert_nickname)
++        self.assertEqual(cert_der, self.cert_der)
+ 
+ #-------------------------------------------------------------------------------
+ 
+ class TestPKCS12Export(unittest.TestCase):
+     def setUp(self):
+-        nss.nss_init(certdir)
++        nss.nss_init(db_name)
+         nss.set_password_callback(password_callback)
+         nss.pkcs12_enable_all_ciphers()
++        self.cert_der = get_cert_der_from_db(cert_nickname)
++        if self.cert_der is None:
++            raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
+ 
+     def tearDown(self):
+         nss.nss_shutdown()
+ 
+     def test_export(self):
+         if verbose: print "test_export"
+-        pkcs12_data = nss.pkcs12_export(export_nickname, pkcs12_file_password)
+-        if write_export_file:
+-            p12_file_path = os.path.join(os.path.dirname(sys.argv[0]), "%s.p12" % export_nickname)
+-            f = open(p12_file_path, 'w')
++        pkcs12_data = nss.pkcs12_export(cert_nickname, pk12_passwd)
++        with open(exported_pk12_filename, 'w') as f:
+             f.write(pkcs12_data)
+-            f.close()
++
++        pk12_listing = list_pk12(pk12_filename)
++        pk12_listing = strip_key_from_pk12_listing(pk12_listing)
++
++        exported_pk12_listing = list_pk12(exported_pk12_filename)
++        exported_pk12_listing = strip_key_from_pk12_listing(exported_pk12_listing)
++
++        self.assertEqual(pk12_listing, exported_pk12_listing)
+ 
+ if __name__ == '__main__':
+     unittest.main()
+diff -N -u -r python-nss-0.14.0/test/util.py python-nss-0.14.1/test/util.py
+--- python-nss-0.14.0/test/util.py	1969-12-31 19:00:00.000000000 -0500
++++ python-nss-0.14.1/test/util.py	2013-06-13 09:58:32.000000000 -0400
+@@ -0,0 +1,40 @@
++import sys
++import os
++from distutils.util import get_platform
++
++def get_build_dir():
++    '''
++    Walk from the current directory up until a directory is found
++    which contains a regular file called "setup.py" and a directory
++    called "build". If found return the fully qualified path to
++    the build directory's platform specific directory, this is where
++    the architecture specific build produced by setup.py is located.
++
++    There is no API in distutils to return the platform specific
++    directory so we use as much as distutils exposes, the rest was
++    determined by looking at the source code for distutils.
++
++    If the build directory cannont be found in the tree None is returned.
++    '''
++    cwd = os.getcwd()
++    path_components = cwd.split('/')
++    while (len(path_components)):
++        path = os.path.join('/', *path_components)
++        setup_path = os.path.join(path, 'setup.py')
++        build_path = os.path.join(path, 'build')
++        # Does this directory contain the file "setup.py" and the directory "build"?
++        if os.path.exists(setup_path) and os.path.exists(build_path) and \
++           os.path.isfile(setup_path) and os.path.isdir(build_path):
++            # Found, return the path contentated with the architecture
++            # specific build directory
++            platform_specifier = "lib.%s-%s" % (get_platform(), sys.version[0:3])
++            return os.path.join(build_path, platform_specifier)
++
++        # Not found, ascend to parent directory and try again
++        path_components.pop()
++
++    # Failed to find the build directory
++    return None
++
++def insert_build_dir_into_path():
++    sys.path.insert(0,get_build_dir())
diff --git a/SPECS/python-nss.spec b/SPECS/python-nss.spec
new file mode 100644
index 0000000..d62c533
--- /dev/null
+++ b/SPECS/python-nss.spec
@@ -0,0 +1,852 @@
+# sitelib for noarch packages, sitearch for others (remove the unneeded one)
+%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
+
+%global build_api_doc 1
+
+Name:           python-nss
+Version:        0.14.0
+Release:        3%{?dist}
+Summary:        Python bindings for Network Security Services (NSS)
+
+Group:          Development/Languages
+License:        MPLv2.0 or GPLv2+ or LGPLv2+
+URL:            ftp://ftp.mozilla.org/pub/mozilla.org/security/python-nss
+Source0:        ftp://ftp.mozilla.org/pub/mozilla.org/security/python-nss/releases/PYNSS_RELEASE_0_14_0/src/python-nss-%{version}.tar.bz2
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+Patch1: python-nss-0.14.1.patch
+
+
+%global docdir %{_docdir}/%{name}-%{version}
+
+# We don't want to provide private python extension libs
+%{?filter_setup:
+%filter_provides_in %{python_sitearch}/.*\.so$
+%filter_setup
+}
+
+BuildRequires: python-devel
+BuildRequires: python-setuptools-devel
+BuildRequires: python-docutils
+BuildRequires: nspr-devel
+BuildRequires: nss-devel
+BuildRequires: epydoc
+
+%description
+This package provides Python bindings for Network Security Services
+(NSS) and the Netscape Portable Runtime (NSPR).
+
+NSS is a set of libraries supporting security-enabled client and
+server applications. Applications built with NSS can support SSL v2
+and v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509 v3
+certificates, and other security standards. Specific NSS
+implementations have been FIPS-140 certified.
+
+%package doc
+Group: Documentation
+Summary: API documentation and examples
+Requires: %{name} = %{version}-%{release}
+
+%description doc
+API documentation and examples
+
+%prep
+%setup -q
+%patch1 -p1 -b .0.14.1
+
+%build
+CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %{__python} setup.py build
+%if %build_api_doc
+%{__python} setup.py build_doc
+%endif
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%{__python} setup.py install  -O1 --install-platlib %{python_sitearch} --skip-build --root $RPM_BUILD_ROOT
+%{__python} setup.py install_doc --docdir %{docdir} --skip-build --root $RPM_BUILD_ROOT
+
+# Remove execution permission from any example/test files in docdir
+find $RPM_BUILD_ROOT/%{docdir} -type f | xargs chmod a-x
+
+# Set correct permissions on .so files
+chmod 0755 $RPM_BUILD_ROOT/%{python_sitearch}/nss/*.so
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%files
+%defattr(-,root,root,-)
+%{python_sitearch}/*
+%doc %{docdir}/ChangeLog
+%doc %{docdir}/LICENSE.gpl
+%doc %{docdir}/LICENSE.lgpl
+%doc %{docdir}/LICENSE.mpl
+%doc %{docdir}/README
+
+%files doc
+%defattr(-,root,root,-)
+%doc %{docdir}/examples
+%doc %{docdir}/test
+%if %build_api_doc
+%doc %{docdir}/api
+%endif
+
+%changelog
+* Fri Oct 18 2013 John Dennis <jdennis@redhat.com> - 0.14.0-3
+- resolves: bug#1003979
+- In coordination with QE with regards to bz 1019934 it was requested
+  the unittest patches be enhanced with a more robust version of
+  test_pkcs12, no actual bug, just better testing.
+
+* Tue Oct  8 2013 John Dennis <jdennis@redhat.com> - 0.14.0-2
+- resolves: bug#1002589
+- resolves: bug#1003979
+
+- Rewrite setup_certs.py. No longer behaves like an expect script
+  which was fragile. By default now creates a sql style database.
+- By default all examples & tests use new sql format for NSS database
+- db-name is now used instead of dbdir to provide distinction between
+  the database directory and it's scheme (e.g. 'sql:')
+- all examples and tests now default db-name to 'sql:pki'
+- replaced legacy getopt & optparse command line argument handling
+  with modern argparse.
+
+* Mon May 13 2013 John Dennis <jdennis@redhat.com> - 0.14-1
+  External Changes:
+  -----------------
+
+  The primary enhancements in this version is support of certifcate
+  validation, OCSP support, and support for the certificate "Authority
+  Information Access" extension.
+
+  Enhanced certifcate validation including CA certs can be done via
+  Certificate.verify() or Certificate.is_ca_cert(). When cert
+  validation fails you can now obtain diagnostic information as to why
+  the cert failed to validate. This is encapsulated in the
+  CertVerifyLog class which is a iterable collection of
+  CertVerifyLogNode objects. Most people will probablby just print the
+  string representation of the returned CertVerifyLog object. Cert
+  validation logging is handled by the Certificate.verify() method.
+  Support has also been added for the various key usage and cert type
+  entities which feature prominently during cert validation.
+
+
+  * Certificate() constructor signature changed from
+
+    Certificate(data=None, der_is_signed=True)
+
+    to
+
+    Certificate(data, certdb=cert_get_default_certdb(), perm=False, nickname=None)
+
+    This change was necessary because all certs should be added to the
+    NSS temporary database when they are loaded, but earlier code
+    failed to to that. It's is not likely that an previous code was
+    failing to pass initialization data or the der_is_signed flag so
+    this change should be backwards compatible.
+
+  * Fix bug #922247, PKCS12Decoder.database_import() method. Importing into
+    a NSS database would sometimes fail or segfault.
+
+  * Error codes and descriptions were updated from upstream NSPR & NSS.
+
+  * The password callback did not allow for breaking out of a password
+    prompting loop, now if None is returned from the password callback
+    the password prompting is terminated.
+
+  * nss.nss_shutdown_context now called from InitContext destructor,
+    this assures the context is shutdown even if the programmer forgot
+    to. It's still best to explicitly shut it down, this is just
+    failsafe.
+
+  * Support was added for shutdown callbacks.
+
+  * The following classes were added:
+    - nss.CertVerifyLogNode
+    - nss.CertVerifyLog
+    - error.CertVerifyError (exception)
+    - nss.AuthorityInfoAccess
+    - nss.AuthorityInfoAccesses
+
+
+  * The following class methods were added:
+    - nss.Certificate.is_ca_cert
+    - nss.Certificate.verify
+    - nss.Certificate.verify_with_log
+    - nss.Certificate.get_cert_chain
+    - nss.Certificate.check_ocsp_status
+    - nss.PK11Slot.list_certs
+    - nss.CertVerifyLogNode.format_lines
+    - nss.CertVerifyLog.format_lines
+    - nss.CRLDistributionPts.format_lines
+
+  * The following class properties were added:
+    - nss.CertVerifyLogNode.certificate
+    - nss.CertVerifyLogNode.error
+    - nss.CertVerifyLogNode.depth
+    - nss.CertVerifyLog.count
+
+  * The following module functions were added:
+    - nss.x509_cert_type
+    - nss.key_usage_flags
+    - nss.list_certs
+    - nss.find_certs_from_email_addr
+    - nss.find_certs_from_nickname
+    - nss.nss_get_version
+    - nss.nss_version_check
+    - nss.set_shutdown_callback
+    - nss.get_use_pkix_for_validation
+    - nss.set_use_pkix_for_validation
+    - nss.enable_ocsp_checking
+    - nss.disable_ocsp_checking
+    - nss.set_ocsp_cache_settings
+    - nss.set_ocsp_failure_mode
+    - nss.set_ocsp_timeout
+    - nss.clear_ocsp_cache
+    - nss.set_ocsp_default_responder
+    - nss.enable_ocsp_default_responder
+    - nss.disable_ocsp_default_responder
+
+  * The following files were added:
+      src/py_traceback.h
+      doc/examples/verify_cert.py
+      test/test_misc.py
+
+  * The following constants were added:
+    - nss.KU_DIGITAL_SIGNATURE
+    - nss.KU_NON_REPUDIATION
+    - nss.KU_KEY_ENCIPHERMENT
+    - nss.KU_DATA_ENCIPHERMENT
+    - nss.KU_KEY_AGREEMENT
+    - nss.KU_KEY_CERT_SIGN
+    - nss.KU_CRL_SIGN
+    - nss.KU_ENCIPHER_ONLY
+    - nss.KU_ALL
+    - nss.KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION
+    - nss.KU_KEY_AGREEMENT_OR_ENCIPHERMENT
+    - nss.KU_NS_GOVT_APPROVED
+    - nss.PK11CertListUnique
+    - nss.PK11CertListUser
+    - nss.PK11CertListRootUnique
+    - nss.PK11CertListCA
+    - nss.PK11CertListCAUnique
+    - nss.PK11CertListUserUnique
+    - nss.PK11CertListAll
+    - nss.certUsageSSLClient
+    - nss.certUsageSSLServer
+    - nss.certUsageSSLServerWithStepUp
+    - nss.certUsageSSLCA
+    - nss.certUsageEmailSigner
+    - nss.certUsageEmailRecipient
+    - nss.certUsageObjectSigner
+    - nss.certUsageUserCertImport
+    - nss.certUsageVerifyCA
+    - nss.certUsageProtectedObjectSigner
+    - nss.certUsageStatusResponder
+    - nss.certUsageAnyCA
+    - nss.ocspMode_FailureIsVerificationFailure
+    - nss.ocspMode_FailureIsNotAVerificationFailure
+
+  * cert_dump.py extended to print NS_CERT_TYPE_EXTENSION
+
+  * cert_usage_flags, nss_init_flags now support optional repr_kind parameter
+
+  Internal Changes:
+  -----------------
+
+  * Reimplement exception handling
+    - NSPRError is now derived from StandardException instead of
+      EnvironmentError. It was never correct to derive from
+      EnvironmentError but was difficult to implement a new subclassed
+      exception with it's own attributes, using EnvironmentError had
+      been expedient.
+
+    - NSPRError now derived from StandardException, provides:
+      * errno (numeric error code)
+      * strerror (error description associated with error code)
+      * error_message (optional detailed message)
+      * error_code (alias for errno)
+      * error_desc (alias for strerror)
+
+    - CertVerifyError derived from NSPRError, extends with:
+      * usages (bitmask of returned usages)
+      * log (CertVerifyLog object)
+
+  * Expose error lookup to sibling modules
+
+  * Use macros for bitmask_to_list functions to reduce code
+    duplication and centralize logic.
+
+  * Add repr_kind parameter to cert_trust_flags_str()
+
+  * Add support for repr_kind AsEnumName to bitstring table lookup.
+
+  * Add cert_type_bitstr_to_tuple() lookup function
+
+  * Add PRTimeConvert(), used to convert Python time values
+    to PRTime, centralizes conversion logic, reduces duplication
+
+  * Add UTF8OrNoneConvert to better handle unicode parameters which
+    are optional.
+
+  * Add Certificate_summary_format_lines() utility to generate
+    concise certificate identification info for output.
+
+  * Certificate_new_from_CERTCertificate now takes add_reference parameter
+    to properly reference count certs, should fix shutdown busy problems.
+
+  * Add print_traceback(), print_cert() debugging support.
+
+* Mon Feb 18 2013 John Dennis <jdennis@redhat.com> - 0.13-1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Mon Oct  8 2012 John Dennis <jdennis@redhat.com> - 0.13-0
+- Update to version 0.13
+  Introduced in 0.13:
+
+  * Fix NSS SECITEM_CompareItem bug via workaround.
+
+  * Fix incorrect format strings in PyArg_ParseTuple* for:
+    - GeneralName
+    - BasicConstraints
+    - cert_x509_key_usage
+
+  * Fix bug when decoding certificate BasicConstraints extension
+
+  * Fix hang in setup_certs.
+
+  * For NSS >= 3.13 support CERTDB_TERMINAL_RECORD
+
+  * You can now query for a specific certificate extension
+    Certficate.get_extension()
+
+  * The following classes were added:
+    - RSAGenParams
+
+  * The following class methods were added:
+    - nss.nss.Certificate.get_extension
+    - nss.nss.PK11Slot.generate_key_pair
+    - nss.nss.DSAPublicKey.format
+    - nss.nss.DSAPublicKey.format_lines
+
+  * The following module functions were added:
+    - nss.nss.pub_wrap_sym_key
+
+  * The following internal utilities were added:
+    - PyString_UTF8
+    - SecItem_new_alloc()
+
+  * The following class constructors were modified to accept
+    intialization parameters
+
+    - KEYPQGParams (DSA generation parameters)
+
+  * The PublicKey formatting (i.e. format_lines) was augmented
+    to format DSA keys (formerly it only recognized RSA keys).
+
+  * Allow lables and values to be justified when printing objects
+
+  * The following were deprecated:
+    - nss.nss.make_line_pairs (replaced by nss.nss.make_line_fmt_tuples)
+
+    Deprecated Functionality:
+    -------------------------
+    - make_line_pairs() has been replaced by make_line_fmt_tuples()
+      because 2-valued tuples were not sufficently general. It is
+      expected very few programs will have used this function, it's mostly
+      used internally but provided as a support utility.
+
+* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.12-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.12-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Thu Nov 17 2011 John Dennis <jdennis@redhat.com> - 0.12-2
+- add patch python-nss-0.12-rsapssparams.patch to fix build problem
+  which appears only with nss 3.13 and later.
+
+* Mon Jun  6 2011 John Dennis <jdennis@redhat.com> - 0.12-1
+  * Major new enhancement is additon of PKCS12 support and
+    AlgorithmID's.
+
+  * setup.py build enhancements
+    - Now searches for the NSS and NSPR header files rather
+      than hardcoding their location. This makes building friendlier
+      on other systems (i.e. debian)
+    - Now takes optional command line arguments, -d or --debug
+      will turn on debug options during the build.
+
+  * Fix reference counting bug in PK11_password_callback() which
+    contributed to NSS not being able to shutdown due to
+    resources still in use.
+
+  * Add UTF-8 support to ssl.config_server_session_id_cache()
+
+  * Added unit tests for cipher, digest, client_server.
+
+  * All unittests now run, added test/run_tests to invoke
+    full test suite.
+
+  * Fix bug in test/setup_certs.py, hardcoded full path to
+    libnssckbi.so was causing failures on 64-bit systems,
+    just use the libnssckbi.so basename, modutil will find
+    it on the standard search path.
+
+  * doc/examples/cert_dump.py uses new AlgorithmID class to
+    dump Signature Algorithm
+
+  * doc/examples/ssl_example.py now can cleanly shutdown NSS.
+
+  * Exception error messages now include PR error text if available.
+
+  * The following classes were replaced:
+    - SignatureAlgorithm replaced by new class AlgorithmID
+
+  * The following classes were added:
+    - AlgorithmID
+    - PKCS12DecodeItem
+    - PKCS12Decoder
+
+  * The following class methods were added:
+    - PK11Slot.authenticate()
+    - PK11Slot.get_disabled_reason()
+    - PK11Slot.has_protected_authentication_path()
+    - PK11Slot.has_root_certs()
+    - PK11Slot.is_disabled()
+    - PK11Slot.is_friendly()
+    - PK11Slot.is_internal()
+    - PK11Slot.is_logged_in()
+    - PK11Slot.is_removable()
+    - PK11Slot.logout()
+    - PK11Slot.need_login()
+    - PK11Slot.need_user_init()
+    - PK11Slot.user_disable()
+    - PK11Slot.user_enable()
+    - PKCS12DecodeItem.format()
+    - PKCS12DecodeItem.format_lines()
+    - PKCS12Decoder.database_import()
+    - PKCS12Decoder.format()
+    - PKCS12Decoder.format_lines()
+
+  * The following class properties were added:
+    - AlgorithmID.id_oid
+    - AlgorithmID.id_str
+    - AlgorithmID.id_tag
+    - AlgorithmID.parameters
+    - PKCS12DecodeItem.certificate
+    - PKCS12DecodeItem.friendly_name
+    - PKCS12DecodeItem.has_key
+    - PKCS12DecodeItem.shroud_algorithm_id
+    - PKCS12DecodeItem.signed_cert_der
+    - PKCS12DecodeItem.type
+    - SignedData.data
+    - SignedData.der
+
+  * The following module functions were added:
+    - nss.nss.dump_certificate_cache_info()
+    - nss.nss.find_slot_by_name()
+    - nss.nss.fingerprint_format_lines()
+    - nss.nss.get_internal_slot()
+    - nss.nss.is_fips()
+    - nss.nss.need_pw_init()
+    - nss.nss.nss_init_read_write()
+    - nss.nss.pk11_disabled_reason_name()
+    - nss.nss.pk11_disabled_reason_str()
+    - nss.nss.pk11_logout_all()
+    - nss.nss.pkcs12_cipher_from_name()
+    - nss.nss.pkcs12_cipher_name()
+    - nss.nss.pkcs12_enable_all_ciphers()
+    - nss.nss.pkcs12_enable_cipher()
+    - nss.nss.pkcs12_export()
+    - nss.nss.pkcs12_map_cipher()
+    - nss.nss.pkcs12_set_nickname_collision_callback()
+    - nss.nss.pkcs12_set_preferred_cipher()
+    - nss.nss.token_exists()
+    - nss.ssl.config_mp_server_sid_cache()
+    - nss.ssl.config_server_session_id_cache_with_opt()
+    - nss.ssl.get_max_server_cache_locks()
+    - nss.ssl.set_max_server_cache_locks()
+    - nss.ssl.shutdown_server_session_id_cache()
+
+  * The following constants were added:
+    - nss.nss.int.PK11_DIS_COULD_NOT_INIT_TOKEN
+    - nss.nss.int.PK11_DIS_NONE
+    - nss.nss.int.PK11_DIS_TOKEN_NOT_PRESENT
+    - nss.nss.int.PK11_DIS_TOKEN_VERIFY_FAILED
+    - nss.nss.int.PK11_DIS_USER_SELECTED
+    - nss.nss.int.PKCS12_DES_56
+    - nss.nss.int.PKCS12_DES_EDE3_168
+    - nss.nss.int.PKCS12_RC2_CBC_128
+    - nss.nss.int.PKCS12_RC2_CBC_40
+    - nss.nss.int.PKCS12_RC4_128
+    - nss.nss.int.PKCS12_RC4_40
+
+  * The following files were added:
+    - test/run_tests
+    - test/test_cipher.py (replaces cipher_test.py)
+    - test/test_client_server.py
+    - test/test_digest.py (replaces digest_test.py)
+    - test/test_pkcs12.py
+
+  * The following were deprecated:
+    - SignatureAlgorithm
+
+* Tue Mar 22 2011 John Dennis <jdennis@redhat.com> - 0.11-2
+- Resolves: #689059
+  Add family parameter to Socket constructors in examples and doc.
+  Mark implicit family parameter as deprecated.
+  Raise exception if Socket family does not match NetworkAddress family.
+  Add --server-subject to setup_certs.py (made testing IPv6 easier without DNS)
+
+* Mon Feb 21 2011 John Dennis <jdennis@redhat.com> - 0.11-1
+  * Better support for IPv6
+
+  * Add AddrInfo class to support IPv6 address resolution. Supports
+    iteration over it's set of NetworkAddress objects and provides
+    hostname, canonical_name object properties.
+
+  * Add PR_AI_* constants.
+
+  * NetworkAddress constructor and NetworkAddress.set_from_string() added
+    optional family parameter. This is necessary for utilizing
+    PR_GetAddrInfoByName().
+
+  * NetworkAddress initialized via a string paramter are now initalized via
+    PR_GetAddrInfoByName using family.
+
+  * Add NetworkAddress.address property to return the address sans the
+    port as a string. NetworkAddress.str() includes the port. For IPv6 the
+    a hex string must be enclosed in brackets if a port is appended to it,
+    the bracketed hex address with appended with a port is unappropriate
+    in some circumstances, hence the new address property to permit either
+    the address string with a port or without a port.
+
+  * Fix the implementation of the NetworkAddress.family property, it was
+    returning bogus data due to wrong native data size.
+
+  * HostEntry objects now support iteration and indexing of their
+    NetworkAddress members.
+
+  * Add io.addr_family_name() function to return string representation of
+    PR_AF_* constants.
+
+  * Modify example and test code to utilize AddrInfo instead of deprecated
+    NetworkAddress functionality. Add address family command argument to
+    ssl_example.
+
+  * Fix pty import statement in test/setup_certs.py
+
+    Deprecated Functionality:
+    -------------------------
+
+  * NetworkAddress initialized via a string paramter is now
+    deprecated. AddrInfo should be used instead.
+
+  * NetworkAddress.set_from_string is now deprecated. AddrInfo should be
+    used instead.
+
+  * NetworkAddress.hostentry is deprecated. It was a bad idea,
+    NetworkAddress objects can support both IPv4 and IPv6, but a HostEntry
+    object can only support IPv4. Plus the implementation depdended on
+    being able to perform a reverse DNS lookup which is not always
+    possible.
+
+  * HostEntry.get_network_addresses() and HostEntry.get_network_address()
+    are now deprecated. In addition their port parameter is now no longer
+    respected. HostEntry objects now support iteration and
+    indexing of their NetworkAddress and that should be used to access
+    their NetworkAddress objects instead.
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.10-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Tue Jan 11 2011 John Dennis <jdennis@redhat.com> - 0.10-3
+- Fix all rpmlint warnings
+- doc for license, changelog etc. now in main package,
+  doc subpackage now only contains api doc, examples, test, etc.
+- Filter provides for .so files
+- Remove execute permission on everything in docdir
+- Capitalize description
+
+* Tue Jan 11 2011 John Dennis <jdennis@redhat.com> - 0.10-2
+- split documentation out into separate doc sub-package
+  and make building api documentation optional
+
+* Mon Jan 10 2011 John Dennis <jdennis@redhat.com> - 0.10-1
+- The following classes were added:
+    InitParameters
+    InitContext
+
+-The following module functions were added:
+    nss.nss.nss_initialize()
+    nss.nss.nss_init_context()
+    nss.nss.nss_shutdown_context()
+    nss.nss.nss_init_flags()
+
+* Thu Jul 22 2010 David Malcolm <dmalcolm@redhat.com> - 0.9-9
+- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
+
+* Fri Jul 16 2010 John Dennis <jdennis@redhat.com> - 0.9-8
+- add nss_is_initialized()
+
+* Thu Jul  8 2010 John Dennis <jdennis@redhat.com> - 0.9-7
+- Remove nss_init_nodb() when nss modules loads from previous version
+  apparently this prevents subsequent calls to nss_init with a
+  database to silently fail.
+- Clean up some cruft in doc/examples/verify_server.py
+
+* Thu Jun 24 2010 John Dennis <jdennis@redhat.com> - 0.9-6
+- Invoke nss_init_nodb() when nss modules loads, this prevents segfaults
+  in NSS if Python programmer forgot to call one of the NSS
+  initialization routines.
+
+- Rename the classes X500Name, X500RDN, X500AVA to DN, RDN, AVA
+  respectively.
+
+- DN and RDN objects now return a list of their contents when indexed by
+  type, this is to support multi-valued items.
+
+- Fix bug where AVA object's string representation did not include it's
+  type.
+
+- Enhance test/test_cert_components.py unit test to test for above
+  changes.
+
+- Add CertificateRequest object
+
+* Mon Jun 14 2010 John Dennis <jdennis@redhat.com> - 0.9-5
+- Fix incomplete read bug (due to read ahead buffer bookkeeping).
+- Remove python-nss specific httplib.py, no longer needed
+  python-nss now compatible with standard library
+- Rewrite httplib_example.py to use standard library and illustrate
+  ssl, non-ssl, connection class, http class usage
+
+* Wed Jun  9 2010 John Dennis <jdennis@redhat.com> - 0.9-4
+- add nss.cert_usage_flags(), use it in ssl_example.py
+
+* Sun Jun  6 2010 John Dennis <jdennis@redhat.com> - 0.9-3
+- Add format_lines() & format() methods to the new certificate extension objects.
+- Add printing of certificate extensions.
+- Add BasicContstraints certificate extension.
+- Fix several reference counting and memory problems discovered with valgrind.
+
+* Tue Jun  1 2010 John Dennis <jdennis@redhat.com> - 0.9-2
+- fold in more ref counting patches from Miloslav Trmač <mitr@redhat.com>
+  into upstream.
+  Did not bump upstream version, just bumped release ver in this spec file.
+
+* Fri May 28 2010 John Dennis <jdennis@redhat.com> - 0.9-1
+- Unicode objects now accepted as well as str objects for
+  interfaces expecting a string.
+
+- Sockets were enhanced thusly:
+    - Threads will now yield during blocking IO.
+    - Socket.makefile() reimplemented
+          file object methods that had been missing (readlines(), sendall(),
+          and iteration) were implemented, makefile now just returns the same
+          Socket object but increments an "open" ref count. Thus a Socket
+          object behaves like a file object and must be closed once for each
+          makefile() call before it's actually closed.
+    - Sockets now support the iter protocol
+    - Add Socket.readlines(), Socket.sendall()
+
+- The following classes were added:
+    AuthKeyID
+    BasicConstraints
+    CRLDistributionPoint
+    CRLDistributionPts
+    CertificateExtension
+    GeneralName
+    SignedCRL
+    X500AVA
+    X500Name
+    X500RDN
+
+- The following module functions were added:
+    nss.nss.cert_crl_reason_from_name()
+    nss.nss.cert_crl_reason_name()
+    nss.nss.cert_general_name_type_from_name()
+    nss.nss.cert_general_name_type_name()
+    nss.nss.cert_usage_flags()
+    nss.nss.decode_der_crl()
+    nss.nss.der_universal_secitem_fmt_lines()
+    nss.nss.import_crl()
+    nss.nss.make_line_pairs()
+    nss.nss.oid_dotted_decimal()
+    nss.nss.oid_str()
+    nss.nss.oid_tag()
+    nss.nss.oid_tag_name()
+    nss.nss.read_der_from_file()
+    nss.nss.x509_alt_name()
+    nss.nss.x509_ext_key_usage()
+    nss.nss.x509_key_usage()
+
+- The following class methods and properties were added:
+  Note: it's a method if the name is suffixed with (), a propety otherwise
+    Socket.next()
+    Socket.readlines()
+    Socket.sendall()
+    SSLSocket.next()
+    SSLSocket.readlines()
+    SSLSocket.sendall()
+    AuthKeyID.key_id
+    AuthKeyID.serial_number
+    AuthKeyID.get_general_names()
+    CRLDistributionPoint.issuer
+    CRLDistributionPoint.get_general_names()
+    CRLDistributionPoint.get_reasons()
+    CertDB.find_crl_by_cert()
+    CertDB.find_crl_by_name()
+    Certificate.extensions
+    CertificateExtension.critical
+    CertificateExtension.name
+    CertificateExtension.oid
+    CertificateExtension.oid_tag
+    CertificateExtension.value
+    GeneralName.type_enum
+    GeneralName.type_name
+    GeneralName.type_string
+    SecItem.der_to_hex()
+    SecItem.get_oid_sequence()
+    SecItem.to_hex()
+    SignedCRL.delete_permanently()
+    X500AVA.oid
+    X500AVA.oid_tag
+    X500AVA.value
+    X500AVA.value_str
+    X500Name.cert_uid
+    X500Name.common_name
+    X500Name.country_name
+    X500Name.dc_name
+    X500Name.email_address
+    X500Name.locality_name
+    X500Name.org_name
+    X500Name.org_unit_name
+    X500Name.state_name
+    X500Name.add_rdn()
+    X500Name.has_key()
+    X500RDN.has_key()
+
+- The following module functions were removed:
+  Note: use nss.nss.oid_tag() instead
+    nss.nss.sec_oid_tag_from_name()
+    nss.nss.sec_oid_tag_name()
+    nss.nss.sec_oid_tag_str()
+
+- The following files were added:
+    doc/examples/cert_dump.py
+    test/test_cert_components.py
+
+- Apply patches from  Miloslav Trmač <mitr@redhat.com>
+  for ref counting and threading support. Thanks Miloslav!
+
+- Review all ref counting, numerous ref counting fixes
+
+- Implement cyclic garbage collection support by
+  adding object traversal and clear methods
+
+- Identify static variables, move to thread local storage
+
+
+* Wed Mar 24 2010 John Dennis <jdennis@redhat.com> - 0.8-2
+- change %%define to %%global
+
+* Mon Sep 21 2009 John Dennis <jdennis@redhat.com> - 0.8-1
+- The following methods, properties  and functions were added:
+  SecItem.type SecItem.len, SecItem.data
+  PK11SymKey.key_data, PK11SymKey.key_length, PK11SymKey.slot
+  create_context_by_sym_key
+  param_from_iv
+  generate_new_param
+  get_iv_length
+  get_block_size
+  get_pad_mechanism
+- SecItem's now support indexing and slicing on their data
+- Clean up parsing and parameter validation of variable arg functions
+
+* Fri Sep 18 2009 John Dennis <jdennis@redhat.com> - 0.7-1
+- add support for symmetric encryption/decryption
+  more support for digests (hashes)
+
+  The following classes were added:
+  PK11SymKey PK11Context
+
+  The following methods and functions were added:
+  get_best_wrap_mechanism          get_best_key_length
+  key_gen                          derive
+  get_key_length                   digest_key
+  clone_context                    digest_begin
+  digest_op                        cipher_op
+  finalize                         digest_final
+  read_hex                         hash_buf
+  sec_oid_tag_str                  sec_oid_tag_name
+  sec_oid_tag_from_name            key_mechanism_type_name
+  key_mechanism_type_from_name     pk11_attribute_type_name
+  pk11_attribute_type_from_name    get_best_slot
+  get_internal_key_slot            create_context_by_sym_key
+  import_sym_key                   create_digest_context
+  param_from_iv                    param_from_algid
+  generate_new_param               algtag_to_mechanism
+  mechanism_to_algtag
+
+  The following files were added:
+  cipher_test.py digest_test.py
+
+* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.6-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Thu Jul  9 2009 John Dennis <jdennis@redhat.com> - 0.6-2
+- restore nss.nssinit(), make deprecated
+
+* Wed Jul  8 2009 John Dennis <jdennis@redhat.com> - 0.6-1
+- fix bug #510343 client_auth_data_callback seg faults if False
+  is returned from callback
+
+* Wed Jul  1 2009 John Dennis <jdennis@redhat.com> - 0.5-1
+- restore ssl.nss_init and ssl.nss_shutdown but make them deprecated
+  add __version__ string to nss module
+
+* Tue Jun 30 2009 John Dennis <jdennis@redhat.com> - 0.4-1
+- add binding for NSS_NoDB_Init(), bug #509002
+  move nss_init and nss_shutdown from ssl module to nss module
+
+* Thu Jun  4 2009 John Dennis <jdennis@redhat.com> - 0.3-1
+- installed source code in Mozilla CVS repository
+  update URL tag to point to CVS repositoy
+  (not yet a valid URL, still have to coordinate with Mozilla)
+  minor tweak to src directory layout
+
+* Mon Jun  1 2009 John Dennis <jdennis@redhat.com> - 0.2-1
+- Convert licensing to MPL tri-license
+- apply patch from bug #472805, (Miloslav Trmač)
+  Don't allow closing a socket twice, that causes crashes.
+  New function nss.io.Socket.new_socket_pair()
+  New function nss.io.Socket.poll()
+  New function nss.io.Socket.import_tcp_socket()
+  New method nss.nss.Certificate.get_subject_common_name()
+  New function nss.nss.generate_random()
+  Fix return value creation in SSLSocket.get_security_status
+  New function nss.ssl.SSLSocket.import_tcp_socket()
+
+* Thu Feb 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Sat Nov 29 2008 Ignacio Vazquez-Abrams <ivazqueznet+rpm@gmail.com> - 0.1-2
+- Rebuild for Python 2.6
+
+* Tue Sep  9 2008 John Dennis <jdennis@redhat.com> - 0.1-1
+- clean up ssl_example.py, fix arg list in get_cert_nicknames,
+   make certdir cmd line arg consistent with other NSS tools
+- update httplib.py to support client auth, add httplib_example.py which illustrates it's use
+- fix some documentation
+- fix some type usage which were unsafe on 64-bit
+
+* Wed Jul  9 2008 John Dennis <jdennis@redhat.com> - 0.0-2
+- add docutils to build requires so restructured text works
+
+* Fri Jun 27 2008 John Dennis <jdennis@redhat.com> - 0.0-1
+- initial release