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 ===============
115 Getting Started
116 ===============
117
118 NSS stores it's certificates and private keys in a security database
119 unlike OpenSSL which references it's certificates and keys via file
120 pathnames. This means unless you already have an NSS Certificate
121 Database (CertDB) the first order of business will be to create
122 one. When a NSS application initializes itself it will need to specify
123 the path to the CertDB (see "Things All NSS programs must do").
124
125 The CertDB is created and manipulated by the command line utilities
126 certutil and modutil. Both of these programs are part of the nss-tools
127 RPM. Documentation for these tools can be found here:
128 http://www.mozilla.org/projects/security/pki/nss/tools
129
130 Here is an example of creating a CertDB and populating it. In the
131 example the CertDB will be created under the directory "./pki", the CA
132 will be called "myca", the database password will be "myca", and the
133 server's hostname will be "myhost.example.com".
134
135 1. Create the database::
136
137 certutil -N -d ./pki
138
139 This creates a new database under the directory ./pki
140
141 2. Create a root CA certificate::
142
143 certutil -d ./pki -S -s "CN=myca" -n myca -x -t "CTu,C,C" -m 1
144
145 This creates an individual certificate and adds it to the
146 certificate database with a subject of "CN=myca", a nickname of
147 "myca", trust flags indicating for SSL indicating it can issue
148 server certificates (C), can issue client certificates (T), and the
149 certificate can be used for authentication and signing (u). For
150 email and object signing it's trusted to create server
151 certificates. The certificate serial number is set to 1.
152
153
154 3. Create a server certificate and sign it. Our example server will
155 use this::
156
157 certutil -d pki -S -c myca -s "CN=myhost.example.com" -n myhost -t "u,u,u" -m 2
158
159 This creates an individual certificate issued by the CA "myca" and
160 adds it to the certificate database with a subject of
161 "CN=myhost.example.com", a nickname of "myhost". The certificate
162 serial number is set to 2.
163
164 4. Import public root CA's::
165
166 modutil -add ca_certs -libfile /usr/lib/libnssckbi.so -dbdir ./pki
167
168 This is necessary to verify certificates presented by a SSL server a
169 NSS client might connect to. When verifying a certificate the NSS
170 library will "walk the certificate chain" back to a root CA which
171 must be trusted. This command imports the well known root CA's as a
172 PKCS #11 module.
173
174
175 ===============================
176 Things All NSS programs must do
177 ===============================
178
179 - Import the NSS/NSPR modules::
180
181 from nss.error import NSPRError
182 import nss.io as io
183 import nss.nss as nss
184 import nss.ssl as ssl
185
186 In the interest of code brevity we drop the leading "nss." from the
187 module namespace.
188
189 - Initialize NSS and indicate the certficate database (CertDB)::
190
191 certdir = './pki'
192 ssl.nssinit(certdir)
193
194 - If you are implementing an SSL server call config_secure_server()
195 (see ssl_example.py)::
196
197 sock = ssl.SSLSocket()
198 sock.config_secure_server(server_cert, priv_key, server_cert_kea)
199
200 **WARNING** you must call config_secure_server() for SSL servers, if
201 you do not call it the most likely result will be the NSS library
202 will segfault (not pretty).
203
204 ========
205 Examples
206 ========
207
208 There are example programs in under "examples" in the documentation
209 directory. On Fedora/RHEL/CentOS systems this will be
210 /usr/share/doc/python-nss.
211
212 The ssl_example.py sample implements both a client and server in one
213 script. You tell it whether to run as a client (-C) or a server (-S)
214 when you invoke it. The sample shows many of the NSS/NSPR calls and
215 fully implements basic non-SSL client/server using NSPR, SSL
216 client/server using NSS, certificate validation, CertDB operations,
217 and client authentication using certificates.
218
219 To get a list of command line options::
220
221 ssl_example.py --help
222
223 Using the above example certificate database server can be run like
224 this::
225
226 ssl_example.py -S -c ./pki -n myhost
227
228 The client can be run like this::
229
230 ssl_example.py -C -c ./pki
231
232 ======
233 Issues
234 ======
235
236 - The current partitioning of the NSS and NSPR API's into Python
237 modules (i.e. the Python namespaces and their symbols) is a first
238 cut and may not be ideal. One should be prepared for name changes as
239 the binding matures.
240
241 - NSPR vs. Python
242
243 An original design goal of NSS was to be portable, however NSS
244 required access to many system level functions which can vary
245 widely between platforms and OS's. Therefore NSPR was written to
246 encapsulate system services such as IO, sockets, threads, timers,
247 etc. into a common API to insulate NSS from the underlying
248 platform.
249
250 In many respects Python and its collection of packages and modules
251 provides the same type of platform independence for applications
252 and libraries and provides it's own implementation of IO, sockets,
253 threads, timers, etc.
254
255 Unfortunately NSPR's and Python's run time abstractions are not
256 the same nor can either be configured to use a different
257 underlying abstraction layer.
258
259 Currently the NSS binding utilizes *only* the NSPR abstraction
260 layer. One consequence of this is it is not possible to create a
261 Python socket and use it as the foundation for any NSS functions
262 expecting a socket, or visa versa.
263
264 You **must** use the nss.io module to create and manipulate a
265 socket used by NSS. You cannot pass this socket to any Python
266 library function expecting a socket. The two are not compatible.
267
268 Here are some reasons for this incompatibility, perhaps in the
269 future we can find a solution but the immediate goal of the NSS
270 Python binding was to expose NSS through Python, not necessarily
271 to solve the larger integration issue of Python run-time and NSPR
272 run-time.
273
274 - NSPR would like to hide the underlying platform socket (in the
275 NSPR code this is called "osfd"). There are NSPR API's which
276 will operate on osfd's
277
278 - One can base a NSPR socket on an existing osfd via:
279
280 - PR_ImportFile()
281 - PR_ImportPipe()
282 - PR_ImportTCPSocket()
283 - PR_ImportUDPSocket()
284
285 - One can obtain the osfd in use by NSPR, either when the
286 osfd was imported or because NSPR created the osfd itself via:
287
288 - PR_FileDesc2NativeHandle();
289
290 But note this function is not meant to be public in the NSPR
291 API and is documented as being deprecated and carries an
292 explicit warning against it's use.
293
294 Once NSPR gets a hold of an osfd it manipulates it in a manner
295 as if it were the only owner of the osfd. Other native code
296 (e.g. the CPython socket code) which operates on the fd may run
297 afoul of NSPR belief it is the only code in the system operating
298 on the fd. For example in CPython the non-blocking flag is
299 directly set on the fd and non-blocking behavior is implemented
300 by the OS. However, NSPR manages non-blocking behavior
301 internally to the NSPR library eschewing direct OS support for
302 non-blocking. Thus CPython and NSPR are in direct conflict over
303 when and how non-blocking is set on an fd. Examples of this
304 problem can be seen in the Python socket.makefile() operation
305 which takes the fd belonging to a system socket, dups it, and
306 calls fdopen() on the dup'ed fd to return a FILE stream (all
307 Python file IO is based on file objects utilizing a FILE
308 stream). However, the dup'ed fd does not share the same
309 non-blocking flag, NSPR explicitly forces the flag off, Python
310 wants to directly manipulate it. Dup'ed fd's share their flags
311 thus if Python operates on the dup'ed fd returned by NSPR it's
312 going to confuse NSPR. Likewise if one sets non-blocking via
313 NSPR then Python won't honor the flag because Python is
314 expecting the flag to be set on the fd, not in some other
315 location (e.g. internal to NSPR).
316
317 - Python's socket implementation is a very thin layer over the
318 Berkely socket API. There is very little abstraction, thus
319 Python and Python program expect to manipulate sockets directly
320 via their fd's.
321
322 - The error and exception model for Python sockets and SSL is an
323 almost direct one-to-one mapping of the Posix and OpenSSL
324 errors. But NSS uses NSPR errors, thus Python code which has
325 exception handlers for sockets and SSL are expecting a complete
326 different set of exceptions.
327
328 - Python's SSL implementation is a very thin layer over the
329 OpenSSL API, there is little abstraction. Thus there is a
330 sizeable body of Python code which expects the OpenSSL model for
331 IO ready and has exception handlers based on OpenSSL.
332
333 ===
334 FAQ
335 ===
336
337 To be added
338
339 """
340 __version__ = '0.11'
341