1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 ============
21 Introduction
22 ============
23
24 This package provides a binding for the Network Security Services
25 (NSS) library. Because NSS directly uses the Netscape Portable Runtime
26 (NSPR) the binding also provides support for NSPR. There is an
27 inherent conflict between NSPR and Python, please see the Issues
28 section for more detail.
29
30 General documentation on NSS can be found here:
31
32 http://www.mozilla.org/projects/security/pki/nss
33
34 General documentation on NSPR can be found here:
35
36 http://developer.mozilla.org/en/docs/NSPR_API_Reference
37
38 Please note, the documentation included with this package already
39 encapsultes most of the information at the above two URL's, but is
40 specific to the python binding of NSS/NSPR. It is suggested you refer
41 to the python-nss documentation.
42
43 Most of the names and symbols in the NSS/NSPR C API have been kept in
44 the nss-python binding and should be instantly familar or
45 recognizable. Python has different naming conventions and the
46 nss-python binding has adhered to the python naming convensions,
47 Classes are camel case, otherwise symbols are all lower case with
48 words seperated by underscores. The constants used by NSS/NSPR in C
49 API have been imported literally to add the programmer who might be
50 referring to the Mozilla NSS/NSPR documentation and/or header files or
51 who is porting an existing C application to python. Minor other
52 changes have been made in the interest of being "Pythonic".
53
54 ===============
55 Getting Started
56 ===============
57
58 NSS stores it's certificates and private keys in a security database
59 unlike OpenSSL which references it's certificates and keys via file
60 pathnames. This means unless you already have an NSS Certificate
61 Database (CertDB) the first order of business will be to create
62 one. When a NSS application initializes itself it will need to specify
63 the path to the CertDB (see "Things All NSS programs must do").
64
65 The CertDB is created and manipulated by the command line utilities
66 certutil and modutil. Both of these programs are part of the nss-tools
67 RPM. Documentation for these tools can be found here:
68 http://www.mozilla.org/projects/security/pki/nss/tools
69
70 Here is an example of creating a CertDB and populating it. In the
71 example the CertDB will be created under the directory "./pki", the CA
72 will be called "myca", the database password will be "myca", and the
73 server's hostname will be "myhost.example.com".
74
75 1. Create the database::
76
77 certutil -N -d ./pki
78
79 This creates a new database under the directory ./pki
80
81 2. Create a root CA certificate::
82
83 certutil -d ./pki -S -s "CN=myca" -n myca -x -t "CTu,C,C" -m 1
84
85 This creates an individual certificate and adds it to the
86 certificate database with a subject of "CN=myca", a nickname of
87 "myca", trust flags indicating for SSL indicating it can issue
88 server certificates (C), can issue client certificates (T), and the
89 certificate can be used for authentication and signing (u). For
90 email and object signing it's trusted to create server
91 certificates. The certificate serial number is set to 1.
92
93
94 3. Create a server certificate and sign it. Our example server will
95 use this::
96
97 certutil -d pki -S -c myca -s "CN=myhost.example.com" -n myhost -t "C,C,C" -m 2
98
99 This creates an individual certificate issued by the CA "myca" and
100 adds it to the certificate database with a subject of
101 "CN=myhost.example.com", a nickname of "myhost". The certificate
102 serial number is set to 2.
103
104 4. Import public root CA's::
105
106 modutil -add ca_certs -libfile /usr/lib/libnssckbi.so -dbdir ./pki
107
108 This is necessary to verify certificates presented by a SSL server a
109 NSS client might connect to. When verifying a certificate the NSS
110 library will "walk the certificate chain" back to a root CA which
111 must be trusted. This command imports the well known root CA's as a
112 PKCS #11 module.
113
114
115 ===============================
116 Things All NSS programs must do
117 ===============================
118
119 - Import the NSS/NSPR modules::
120
121 from nss.error import NSPRError
122 import nss.io as io
123 import nss.nss as nss
124 import nss.ssl as ssl
125
126 In the interest of code brevity we drop the leading "nss." from the
127 module namespace.
128
129 - Initialize NSS and indicate the certficate database (CertDB)::
130
131 certdir = './pki'
132 ssl.nssinit(certdir)
133
134 - If you are implementing an SSL server call config_secure_server()
135 (see ssl_example.py)::
136
137 sock = ssl.SSLSocket()
138 sock.config_secure_server(server_cert, priv_key, server_cert_kea)
139
140 **WARNING** you must call config_secure_server() for SSL servers, if
141 you do not call it the most likely result will be the NSS library
142 will segfault (not pretty).
143
144 ========
145 Examples
146 ========
147
148 There are example programs in under "examples" in the documentation
149 directory. On Fedora/RHEL/CentOS systems this will be
150 /usr/share/doc/python-nss.
151
152 The ssl_example.py sample implements both a client and server in one
153 script. You tell it whether to run as a client (-C) or a server (-S)
154 when you invoke it. The sample shows many of the NSS/NSPR calls and
155 fully implements basic non-SSL client/server using NSPR, SSL
156 client/server using NSS, certificate validation, CertDB operations,
157 and client authentication using certificates.
158
159 To get a list of command line options::
160
161 ssl_example.py --help
162
163 Using the above example certificate database server can be run like
164 this::
165
166 ssl_example.py -S -c ./pki -n myhost
167
168 The client can be run like this::
169
170 ssl_example.py -C -c ./pki
171
172 ======
173 Issues
174 ======
175
176 - The current partitioning of the NSS and NSPR API's into Python
177 modules (i.e. the Python namespaces and their symbols) is a first
178 cut and may not be ideal. One should be prepared for name changes as
179 the binding matures.
180
181 - NSPR vs. Python
182
183 An original design goal of NSS was to be portable, however NSS
184 required access to many system level functions which can vary
185 widely between platforms and OS's. Therefore NSPR was written to
186 encapsulate system services such as IO, sockets, threads, timers,
187 etc. into a common API to insulate NSS from the underlying
188 platform.
189
190 In many respects Python and its collection of packages and modules
191 provides the same type of platform independence for applications
192 and libraries and provides it's own implementation of IO, sockets,
193 threads, timers, etc.
194
195 Unfortunately NSPR's and Python's run time abstractions are not
196 the same nor can either be configured to use a different
197 underlying abstraction layer.
198
199 Currently the NSS binding utilizes *only* the NSPR abstraction
200 layer. One consequence of this is it is not possible to create a
201 Python socket and use it as the foundation for any NSS functions
202 expecting a socket, or visa versa.
203
204 You **must** use the nss.io module to create and manipulate a
205 socket used by NSS. You cannot pass this socket to any Python
206 library function expecting a socket. The two are not compatible.
207
208 Here are some reasons for this incompatibility, perhaps in the
209 future we can find a solution but the immediate goal of the NSS
210 Python binding was to expose NSS through Python, not necessarily
211 to solve the larger integration issue of Python run-time and NSPR
212 run-time.
213
214 - NSPR would like to hide the underlying platform socket (in the
215 NSPR code this is called "osfd"). There are NSPR API's which
216 will operate on osfd's
217
218 - One can base a NSPR socket on an existing osfd via:
219
220 - PR_ImportFile()
221 - PR_ImportPipe()
222 - PR_ImportTCPSocket()
223 - PR_ImportUDPSocket()
224
225 - One can obtain the osfd in use by NSPR, either when the
226 osfd was imported or because NSPR created the osfd itself via:
227
228 - PR_FileDesc2NativeHandle();
229
230 But note this function is not meant to be public in the NSPR
231 API and is documented as being deprecated and carries an
232 explicit warning against it's use.
233
234 Once NSPR gets a hold of an osfd it manipulates it in a manner
235 as if it were the only owner of the osfd. Other native code
236 (e.g. the CPython socket code) which operates on the fd may run
237 afoul of NSPR belief it is the only code in the system operating
238 on the fd. For example in CPython the non-blocking flag is
239 directly set on the fd and non-blocking behavior is implemented
240 by the OS. However, NSPR manages non-blocking behavior
241 internally to the NSPR library eschewing direct OS support for
242 non-blocking. Thus CPython and NSPR are in direct conflict over
243 when and how non-blocking is set on an fd. Examples of this
244 problem can be seen in the Python socket.makefile() operation
245 which takes the fd belonging to a system socket, dups it, and
246 calls fdopen() on the dup'ed fd to return a FILE stream (all
247 Python file IO is based on file objects utilizing a FILE
248 stream). However, the dup'ed fd does not share the same
249 non-blocking flag, NSPR explicitly forces the flag off, Python
250 wants to directly manipulate it. Dup'ed fd's share their flags
251 thus if Python operates on the dup'ed fd returned by NSPR it's
252 going to confuse NSPR. Likewise if one sets non-blocking via
253 NSPR then Python won't honor the flag because Python is
254 expecting the flag to be set on the fd, not in some other
255 location (e.g. internal to NSPR).
256
257 - Python's socket implementation is a very thin layer over the
258 Berkely socket API. There is very little abstraction, thus
259 Python and Python program expect to manipulate sockets directly
260 via their fd's.
261
262 - The error and exception model for Python sockets and SSL is an
263 almost direct one-to-one mapping of the Posix and OpenSSL
264 errors. But NSS uses NSPR errors, thus Python code which has
265 exception handlers for sockets and SSL are expecting a complete
266 different set of exceptions.
267
268 - Python's SSL implementation is a very thin layer over the
269 OpenSSL API, there is little abstraction. Thus there is a
270 sizeable body of Python code which expects the OpenSSL model for
271 IO ready and has exception handlers based on OpenSSL.
272
273
274 ===
275 FAQ
276 ===
277
278 To be added
279
280 """
281