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