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