/src/nss/lib/pk11wrap/pk11pars.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* This Source Code Form is subject to the terms of the Mozilla Public  | 
2  |  |  * License, v. 2.0. If a copy of the MPL was not distributed with this  | 
3  |  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */  | 
4  |  | /*  | 
5  |  |  * The following handles the loading, unloading and management of  | 
6  |  |  * various PCKS #11 modules  | 
7  |  |  */  | 
8  |  |  | 
9  |  | #include <ctype.h>  | 
10  |  | #include <assert.h>  | 
11  |  | #include "pkcs11.h"  | 
12  |  | #include "seccomon.h"  | 
13  |  | #include "secmod.h"  | 
14  |  | #include "secmodi.h"  | 
15  |  | #include "secmodti.h"  | 
16  |  | #include "pki3hack.h"  | 
17  |  | #include "secerr.h"  | 
18  |  | #include "nss.h"  | 
19  |  | #include "utilpars.h"  | 
20  |  | #include "pk11pub.h"  | 
21  |  |  | 
22  |  | /* create a new module */  | 
23  |  | static SECMODModule *  | 
24  |  | secmod_NewModule(void)  | 
25  | 2  | { | 
26  | 2  |     SECMODModule *newMod;  | 
27  | 2  |     PLArenaPool *arena;  | 
28  |  |  | 
29  |  |     /* create an arena in which dllName and commonName can be  | 
30  |  |      * allocated.  | 
31  |  |      */  | 
32  | 2  |     arena = PORT_NewArena(512);  | 
33  | 2  |     if (arena == NULL) { | 
34  | 0  |         return NULL;  | 
35  | 0  |     }  | 
36  |  |  | 
37  | 2  |     newMod = (SECMODModule *)PORT_ArenaAlloc(arena, sizeof(SECMODModule));  | 
38  | 2  |     if (newMod == NULL) { | 
39  | 0  |         PORT_FreeArena(arena, PR_FALSE);  | 
40  | 0  |         return NULL;  | 
41  | 0  |     }  | 
42  |  |  | 
43  |  |     /*  | 
44  |  |      * initialize of the fields of the module  | 
45  |  |      */  | 
46  | 2  |     newMod->arena = arena;  | 
47  | 2  |     newMod->internal = PR_FALSE;  | 
48  | 2  |     newMod->loaded = PR_FALSE;  | 
49  | 2  |     newMod->isFIPS = PR_FALSE;  | 
50  | 2  |     newMod->dllName = NULL;  | 
51  | 2  |     newMod->commonName = NULL;  | 
52  | 2  |     newMod->library = NULL;  | 
53  | 2  |     newMod->functionList = NULL;  | 
54  | 2  |     newMod->slotCount = 0;  | 
55  | 2  |     newMod->slots = NULL;  | 
56  | 2  |     newMod->slotInfo = NULL;  | 
57  | 2  |     newMod->slotInfoCount = 0;  | 
58  | 2  |     newMod->refCount = 1;  | 
59  | 2  |     newMod->ssl[0] = 0;  | 
60  | 2  |     newMod->ssl[1] = 0;  | 
61  | 2  |     newMod->libraryParams = NULL;  | 
62  | 2  |     newMod->moduleDBFunc = NULL;  | 
63  | 2  |     newMod->parent = NULL;  | 
64  | 2  |     newMod->isCritical = PR_FALSE;  | 
65  | 2  |     newMod->isModuleDB = PR_FALSE;  | 
66  | 2  |     newMod->moduleDBOnly = PR_FALSE;  | 
67  | 2  |     newMod->trustOrder = 0;  | 
68  | 2  |     newMod->cipherOrder = 0;  | 
69  | 2  |     newMod->evControlMask = 0;  | 
70  | 2  |     newMod->refLock = PZ_NewLock(nssILockRefLock);  | 
71  | 2  |     if (newMod->refLock == NULL) { | 
72  | 0  |         PORT_FreeArena(arena, PR_FALSE);  | 
73  | 0  |         return NULL;  | 
74  | 0  |     }  | 
75  | 2  |     return newMod;  | 
76  | 2  | }  | 
77  |  |  | 
78  |  | /* private flags for isModuleDB (field in SECMODModule). */  | 
79  |  | /* The meaing of these flags is as follows:  | 
80  |  |  *  | 
81  |  |  * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the  | 
82  |  |  *   database of other modules to load. Module DBs are loadable modules that  | 
83  |  |  *   tells NSS which PKCS #11 modules to load and when. These module DBs are  | 
84  |  |  *   chainable. That is, one module DB can load another one. NSS system init  | 
85  |  |  *   design takes advantage of this feature. In system NSS, a fixed system  | 
86  |  |  *   module DB loads the system defined libraries, then chains out to the  | 
87  |  |  *   traditional module DBs to load any system or user configured modules  | 
88  |  |  *   (like smart cards). This bit is the same as the already existing meaning  | 
89  |  |  *   of  isModuleDB = PR_TRUE. None of the other module db flags should be set  | 
90  |  |  *   if this flag isn't on.  | 
91  |  |  *  | 
92  |  |  * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first  | 
93  |  |  *   PKCS #11 module presented by a module DB. This allows the OS to load a  | 
94  |  |  *   softoken from the system module, then ask the existing module DB code to  | 
95  |  |  *   load the other PKCS #11 modules in that module DB (skipping it's request  | 
96  |  |  *   to load softoken). This gives the system init finer control over the  | 
97  |  |  *   configuration of that softoken module.  | 
98  |  |  *  | 
99  |  |  * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a  | 
100  |  |  *   different module DB as the 'default' module DB (the one in which  | 
101  |  |  *   'Add module' changes will go). Without this flag NSS takes the first  | 
102  |  |  *   module as the default Module DB, but in system NSS, that first module  | 
103  |  |  *   is the system module, which is likely read only (at least to the user).  | 
104  |  |  *   This  allows system NSS to delegate those changes to the user's module DB,  | 
105  |  |  *   preserving the user's ability to load new PKCS #11 modules (which only  | 
106  |  |  *   affect him), from existing applications like Firefox.  | 
107  |  |  */  | 
108  | 1  | #define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the \  | 
109  |  |                                                  *other flags are set */  | 
110  | 1  | #define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02  | 
111  | 1  | #define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04  | 
112  | 2  | #define SECMOD_FLAG_MODULE_DB_POLICY_ONLY 0x08  | 
113  |  |  | 
114  |  | /* private flags for internal (field in SECMODModule). */  | 
115  |  | /* The meaing of these flags is as follows:  | 
116  |  |  *  | 
117  |  |  * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is  | 
118  |  |  *   the internal module (that is, softoken). This bit is the same as the  | 
119  |  |  *   already existing meaning of internal = PR_TRUE. None of the other  | 
120  |  |  *   internal flags should be set if this flag isn't on.  | 
121  |  |  *  | 
122  |  |  * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark  | 
123  |  |  *   a  different slot returned byt PK11_GetInternalKeySlot(). The 'primary'  | 
124  |  |  *   slot defined by this module will be the new internal key slot.  | 
125  |  |  */  | 
126  | 2  | #define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of \  | 
127  |  |                                                *the other flags are set */  | 
128  | 4  | #define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02  | 
129  |  |  | 
130  |  | /* private flags for policy check. */  | 
131  | 0  | #define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01  | 
132  | 0  | #define SECMOD_FLAG_POLICY_CHECK_VALUE 0x02  | 
133  |  |  | 
134  |  | /*  | 
135  |  |  * for 3.4 we continue to use the old SECMODModule structure  | 
136  |  |  */  | 
137  |  | SECMODModule *  | 
138  |  | SECMOD_CreateModule(const char *library, const char *moduleName,  | 
139  |  |                     const char *parameters, const char *nss)  | 
140  | 0  | { | 
141  | 0  |     return SECMOD_CreateModuleEx(library, moduleName, parameters, nss, NULL);  | 
142  | 0  | }  | 
143  |  |  | 
144  |  | /*  | 
145  |  |  * NSS config options format:  | 
146  |  |  *  | 
147  |  |  * The specified ciphers will be allowed by policy, but an application  | 
148  |  |  * may allow more by policy explicitly:  | 
149  |  |  * config="allow=curve1:curve2:hash1:hash2:rsa-1024..."  | 
150  |  |  *  | 
151  |  |  * Only the specified hashes and curves will be allowed:  | 
152  |  |  * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1"  | 
153  |  |  *  | 
154  |  |  * Only the specified hashes and curves will be allowed, and  | 
155  |  |  *  RSA keys of 2048 or more will be accepted, and DH key exchange  | 
156  |  |  *  with 1024-bit primes or more:  | 
157  |  |  * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1:min-rsa=2048:min-dh=1024"  | 
158  |  |  *  | 
159  |  |  * A policy that enables the AES ciphersuites and the SECP256/384 curves:  | 
160  |  |  * config="allow=aes128-cbc:aes128-gcm:TLS1.0:TLS1.2:TLS1.1:HMAC-SHA1:SHA1:SHA256:SHA384:RSA:ECDHE-RSA:SECP256R1:SECP384R1"  | 
161  |  |  *  | 
162  |  |  * Disallow values are parsed first, then allow values, independent of the  | 
163  |  |  * order they appear.  | 
164  |  |  *  | 
165  |  |  * flags: turn on the following flags:  | 
166  |  |  *    policy-lock: turn off the ability for applications to change policy with  | 
167  |  |  *                 the call NSS_SetAlgorithmPolicy or the other system policy  | 
168  |  |  *                 calls (SSL_SetPolicy, etc.)  | 
169  |  |  *    ssl-lock:    turn off the ability to change the ssl defaults.  | 
170  |  |  *  | 
171  |  |  * The following only apply to ssl cipher suites (future smime)  | 
172  |  |  *  | 
173  |  |  * enable: turn on ciphersuites by default.  | 
174  |  |  * disable: turn off ciphersuites by default without disallowing them by policy.  | 
175  |  |  *  | 
176  |  |  *  | 
177  |  |  */  | 
178  |  |  | 
179  |  | typedef struct { | 
180  |  |     const char *name;  | 
181  |  |     unsigned name_size;  | 
182  |  |     SECOidTag oid;  | 
183  |  |     PRUint32 val;  | 
184  |  | } oidValDef;  | 
185  |  |  | 
186  |  | typedef struct { | 
187  |  |     const char *name;  | 
188  |  |     unsigned name_size;  | 
189  |  |     PRInt32 option;  | 
190  |  | } optionFreeDef;  | 
191  |  |  | 
192  |  | typedef struct { | 
193  |  |     const char *name;  | 
194  |  |     unsigned name_size;  | 
195  |  |     PRUint32 flag;  | 
196  |  | } policyFlagDef;  | 
197  |  |  | 
198  |  | /*  | 
199  |  |  *  This table should be merged with the SECOID table.  | 
200  |  |  */  | 
201  |  | #define CIPHER_NAME(x) x, (sizeof(x) - 1)  | 
202  |  | static const oidValDef curveOptList[] = { | 
203  |  |     /* Curves */  | 
204  |  |     { CIPHER_NAME("PRIME192V1"), SEC_OID_ANSIX962_EC_PRIME192V1, | 
205  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
206  |  |     { CIPHER_NAME("PRIME192V2"), SEC_OID_ANSIX962_EC_PRIME192V2, | 
207  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
208  |  |     { CIPHER_NAME("PRIME192V3"), SEC_OID_ANSIX962_EC_PRIME192V3, | 
209  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
210  |  |     { CIPHER_NAME("PRIME239V1"), SEC_OID_ANSIX962_EC_PRIME239V1, | 
211  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
212  |  |     { CIPHER_NAME("PRIME239V2"), SEC_OID_ANSIX962_EC_PRIME239V2, | 
213  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
214  |  |     { CIPHER_NAME("PRIME239V3"), SEC_OID_ANSIX962_EC_PRIME239V3, | 
215  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
216  |  |     { CIPHER_NAME("PRIME256V1"), SEC_OID_ANSIX962_EC_PRIME256V1, | 
217  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
218  |  |     { CIPHER_NAME("SECP112R1"), SEC_OID_SECG_EC_SECP112R1, | 
219  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
220  |  |     { CIPHER_NAME("SECP112R2"), SEC_OID_SECG_EC_SECP112R2, | 
221  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
222  |  |     { CIPHER_NAME("SECP128R1"), SEC_OID_SECG_EC_SECP128R1, | 
223  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
224  |  |     { CIPHER_NAME("SECP128R2"), SEC_OID_SECG_EC_SECP128R2, | 
225  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
226  |  |     { CIPHER_NAME("SECP160K1"), SEC_OID_SECG_EC_SECP160K1, | 
227  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
228  |  |     { CIPHER_NAME("SECP160R1"), SEC_OID_SECG_EC_SECP160R1, | 
229  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
230  |  |     { CIPHER_NAME("SECP160R2"), SEC_OID_SECG_EC_SECP160R2, | 
231  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
232  |  |     { CIPHER_NAME("SECP192K1"), SEC_OID_SECG_EC_SECP192K1, | 
233  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
234  |  |     { CIPHER_NAME("SECP192R1"), SEC_OID_ANSIX962_EC_PRIME192V1, | 
235  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
236  |  |     { CIPHER_NAME("SECP224K1"), SEC_OID_SECG_EC_SECP224K1, | 
237  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
238  |  |     { CIPHER_NAME("SECP256K1"), SEC_OID_SECG_EC_SECP256K1, | 
239  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
240  |  |     { CIPHER_NAME("SECP256R1"), SEC_OID_ANSIX962_EC_PRIME256V1, | 
241  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
242  |  |     { CIPHER_NAME("SECP384R1"), SEC_OID_SECG_EC_SECP384R1, | 
243  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
244  |  |     { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1, | 
245  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
246  |  |     { CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519, | 
247  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
248  |  |     { CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00, 0 }, | 
249  |  |     { CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519, 0 }, | 
250  |  |     /* ANSI X9.62 named elliptic curves (characteristic two field) */  | 
251  |  |     { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1, | 
252  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
253  |  |     { CIPHER_NAME("C2PNB163V2"), SEC_OID_ANSIX962_EC_C2PNB163V2, | 
254  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
255  |  |     { CIPHER_NAME("C2PNB163V3"), SEC_OID_ANSIX962_EC_C2PNB163V3, | 
256  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
257  |  |     { CIPHER_NAME("C2PNB176V1"), SEC_OID_ANSIX962_EC_C2PNB176V1, | 
258  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
259  |  |     { CIPHER_NAME("C2TNB191V1"), SEC_OID_ANSIX962_EC_C2TNB191V1, | 
260  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
261  |  |     { CIPHER_NAME("C2TNB191V2"), SEC_OID_ANSIX962_EC_C2TNB191V2, | 
262  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
263  |  |     { CIPHER_NAME("C2TNB191V3"), SEC_OID_ANSIX962_EC_C2TNB191V3, | 
264  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
265  |  |     { CIPHER_NAME("C2ONB191V4"), SEC_OID_ANSIX962_EC_C2ONB191V4, | 
266  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
267  |  |     { CIPHER_NAME("C2ONB191V5"), SEC_OID_ANSIX962_EC_C2ONB191V5, | 
268  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
269  |  |     { CIPHER_NAME("C2PNB208W1"), SEC_OID_ANSIX962_EC_C2PNB208W1, | 
270  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
271  |  |     { CIPHER_NAME("C2TNB239V1"), SEC_OID_ANSIX962_EC_C2TNB239V1, | 
272  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
273  |  |     { CIPHER_NAME("C2TNB239V2"), SEC_OID_ANSIX962_EC_C2TNB239V2, | 
274  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
275  |  |     { CIPHER_NAME("C2TNB239V3"), SEC_OID_ANSIX962_EC_C2TNB239V3, | 
276  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
277  |  |     { CIPHER_NAME("C2ONB239V4"), SEC_OID_ANSIX962_EC_C2ONB239V4, | 
278  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
279  |  |     { CIPHER_NAME("C2ONB239V5"), SEC_OID_ANSIX962_EC_C2ONB239V5, | 
280  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
281  |  |     { CIPHER_NAME("C2PNB272W1"), SEC_OID_ANSIX962_EC_C2PNB272W1, | 
282  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
283  |  |     { CIPHER_NAME("C2PNB304W1"), SEC_OID_ANSIX962_EC_C2PNB304W1, | 
284  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
285  |  |     { CIPHER_NAME("C2TNB359V1"), SEC_OID_ANSIX962_EC_C2TNB359V1, | 
286  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
287  |  |     { CIPHER_NAME("C2PNB368W1"), SEC_OID_ANSIX962_EC_C2PNB368W1, | 
288  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
289  |  |     { CIPHER_NAME("C2TNB431R1"), SEC_OID_ANSIX962_EC_C2TNB431R1, | 
290  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
291  |  |     /* SECG named elliptic curves (characteristic two field) */  | 
292  |  |     { CIPHER_NAME("SECT113R1"), SEC_OID_SECG_EC_SECT113R1, | 
293  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
294  |  |     { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT113R2, | 
295  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
296  |  |     { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT131R1, | 
297  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
298  |  |     { CIPHER_NAME("SECT131R2"), SEC_OID_SECG_EC_SECT131R2, | 
299  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
300  |  |     { CIPHER_NAME("SECT163K1"), SEC_OID_SECG_EC_SECT163K1, | 
301  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
302  |  |     { CIPHER_NAME("SECT163R1"), SEC_OID_SECG_EC_SECT163R1, | 
303  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
304  |  |     { CIPHER_NAME("SECT163R2"), SEC_OID_SECG_EC_SECT163R2, | 
305  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
306  |  |     { CIPHER_NAME("SECT193R1"), SEC_OID_SECG_EC_SECT193R1, | 
307  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
308  |  |     { CIPHER_NAME("SECT193R2"), SEC_OID_SECG_EC_SECT193R2, | 
309  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
310  |  |     { CIPHER_NAME("SECT233K1"), SEC_OID_SECG_EC_SECT233K1, | 
311  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
312  |  |     { CIPHER_NAME("SECT233R1"), SEC_OID_SECG_EC_SECT233R1, | 
313  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
314  |  |     { CIPHER_NAME("SECT239K1"), SEC_OID_SECG_EC_SECT239K1, | 
315  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
316  |  |     { CIPHER_NAME("SECT283K1"), SEC_OID_SECG_EC_SECT283K1, | 
317  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
318  |  |     { CIPHER_NAME("SECT283R1"), SEC_OID_SECG_EC_SECT283R1, | 
319  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
320  |  |     { CIPHER_NAME("SECT409K1"), SEC_OID_SECG_EC_SECT409K1, | 
321  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
322  |  |     { CIPHER_NAME("SECT409R1"), SEC_OID_SECG_EC_SECT409R1, | 
323  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
324  |  |     { CIPHER_NAME("SECT571K1"), SEC_OID_SECG_EC_SECT571K1, | 
325  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
326  |  |     { CIPHER_NAME("SECT571R1"), SEC_OID_SECG_EC_SECT571R1, | 
327  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },  | 
328  |  | };  | 
329  |  |  | 
330  |  | static const oidValDef hashOptList[] = { | 
331  |  |     /* Hashes */  | 
332  |  |     { CIPHER_NAME("MD2"), SEC_OID_MD2, | 
333  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
334  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
335  |  |     { CIPHER_NAME("MD4"), SEC_OID_MD4, | 
336  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
337  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
338  |  |     { CIPHER_NAME("MD5"), SEC_OID_MD5, | 
339  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
340  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
341  |  |     { CIPHER_NAME("SHA1"), SEC_OID_SHA1, | 
342  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
343  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
344  |  |     { CIPHER_NAME("SHA224"), SEC_OID_SHA224, | 
345  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
346  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
347  |  |     { CIPHER_NAME("SHA256"), SEC_OID_SHA256, | 
348  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
349  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
350  |  |     { CIPHER_NAME("SHA384"), SEC_OID_SHA384, | 
351  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
352  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
353  |  |     { CIPHER_NAME("SHA512"), SEC_OID_SHA512, | 
354  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
355  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
356  |  |     { CIPHER_NAME("SHA3-224"), SEC_OID_SHA3_224, | 
357  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
358  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
359  |  |     { CIPHER_NAME("SHA3-256"), SEC_OID_SHA3_256, | 
360  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
361  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
362  |  |     { CIPHER_NAME("SHA3-384"), SEC_OID_SHA3_384, | 
363  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
364  |  |           NSS_USE_ALG_IN_PKCS12 },  | 
365  |  |     { CIPHER_NAME("SHA3-512"), SEC_OID_SHA3_512, | 
366  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |  | 
367  |  |           NSS_USE_ALG_IN_PKCS12 }  | 
368  |  | };  | 
369  |  |  | 
370  |  | static const oidValDef macOptList[] = { | 
371  |  |     /* MACs */  | 
372  |  |     { CIPHER_NAME("HMAC-MD5"), SEC_OID_HMAC_MD5, | 
373  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
374  |  |     { CIPHER_NAME("HMAC-SHA1"), SEC_OID_HMAC_SHA1, | 
375  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
376  |  |     { CIPHER_NAME("HMAC-SHA224"), SEC_OID_HMAC_SHA224, | 
377  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
378  |  |     { CIPHER_NAME("HMAC-SHA256"), SEC_OID_HMAC_SHA256, | 
379  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
380  |  |     { CIPHER_NAME("HMAC-SHA384"), SEC_OID_HMAC_SHA384, | 
381  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
382  |  |     { CIPHER_NAME("HMAC-SHA512"), SEC_OID_HMAC_SHA512, | 
383  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
384  |  |     { CIPHER_NAME("HMAC-SHA3-224"), SEC_OID_HMAC_SHA3_224, | 
385  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
386  |  |     { CIPHER_NAME("HMAC-SHA3-256"), SEC_OID_HMAC_SHA3_256, | 
387  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
388  |  |     { CIPHER_NAME("HMAC-SHA3-384"), SEC_OID_HMAC_SHA3_384, | 
389  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
390  |  |     { CIPHER_NAME("HMAC-SHA3-512"), SEC_OID_HMAC_SHA3_512, | 
391  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },  | 
392  |  | };  | 
393  |  |  | 
394  |  | static const oidValDef cipherOptList[] = { | 
395  |  |     /* Ciphers */  | 
396  |  |     { CIPHER_NAME("AES128-CBC"), SEC_OID_AES_128_CBC, | 
397  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
398  |  |     { CIPHER_NAME("AES192-CBC"), SEC_OID_AES_192_CBC, | 
399  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
400  |  |     { CIPHER_NAME("AES256-CBC"), SEC_OID_AES_256_CBC, | 
401  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
402  |  |     { CIPHER_NAME("AES128-GCM"), SEC_OID_AES_128_GCM, NSS_USE_ALG_IN_SSL }, | 
403  |  |     { CIPHER_NAME("AES192-GCM"), SEC_OID_AES_192_GCM, NSS_USE_ALG_IN_SSL }, | 
404  |  |     { CIPHER_NAME("AES256-GCM"), SEC_OID_AES_256_GCM, NSS_USE_ALG_IN_SSL }, | 
405  |  |     { CIPHER_NAME("CAMELLIA128-CBC"), SEC_OID_CAMELLIA_128_CBC, | 
406  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
407  |  |     { CIPHER_NAME("CAMELLIA192-CBC"), SEC_OID_CAMELLIA_192_CBC, | 
408  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
409  |  |     { CIPHER_NAME("CAMELLIA256-CBC"), SEC_OID_CAMELLIA_256_CBC, | 
410  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
411  |  |     { CIPHER_NAME("CHACHA20-POLY1305"), SEC_OID_CHACHA20_POLY1305, NSS_USE_ALG_IN_SSL }, | 
412  |  |     { CIPHER_NAME("SEED-CBC"), SEC_OID_SEED_CBC, | 
413  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
414  |  |     { CIPHER_NAME("DES-EDE3-CBC"), SEC_OID_DES_EDE3_CBC, | 
415  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
416  |  |     { CIPHER_NAME("DES-40-CBC"), SEC_OID_DES_40_CBC, | 
417  |  |       NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },  | 
418  |  |     { CIPHER_NAME("DES-CBC"), SEC_OID_DES_CBC, NSS_USE_ALG_IN_SSL }, | 
419  |  |     { CIPHER_NAME("NULL-CIPHER"), SEC_OID_NULL_CIPHER, NSS_USE_ALG_IN_SSL }, | 
420  |  |     { CIPHER_NAME("RC2"), SEC_OID_RC2_CBC, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 }, | 
421  |  |     { CIPHER_NAME("RC2-40-CBC"), SEC_OID_RC2_40_CBC, NSS_USE_ALG_IN_SMIME }, | 
422  |  |     { CIPHER_NAME("RC2-64-CBC"), SEC_OID_RC2_64_CBC, NSS_USE_ALG_IN_SMIME }, | 
423  |  |     { CIPHER_NAME("RC2-128-CBC"), SEC_OID_RC2_128_CBC, NSS_USE_ALG_IN_SMIME }, | 
424  |  |     { CIPHER_NAME("RC4"), SEC_OID_RC4, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 }, | 
425  |  |     { CIPHER_NAME("IDEA"), SEC_OID_IDEA_CBC, NSS_USE_ALG_IN_SSL }, | 
426  |  | };  | 
427  |  |  | 
428  |  | static const oidValDef kxOptList[] = { | 
429  |  |     /* Key exchange */  | 
430  |  |     { CIPHER_NAME("RSA"), SEC_OID_TLS_RSA, NSS_USE_ALG_IN_SSL_KX }, | 
431  |  |     { CIPHER_NAME("RSA-EXPORT"), SEC_OID_TLS_RSA_EXPORT, NSS_USE_ALG_IN_SSL_KX }, | 
432  |  |     { CIPHER_NAME("DHE-RSA"), SEC_OID_TLS_DHE_RSA, NSS_USE_ALG_IN_SSL_KX }, | 
433  |  |     { CIPHER_NAME("DHE-DSS"), SEC_OID_TLS_DHE_DSS, NSS_USE_ALG_IN_SSL_KX }, | 
434  |  |     { CIPHER_NAME("DH-RSA"), SEC_OID_TLS_DH_RSA, NSS_USE_ALG_IN_SSL_KX }, | 
435  |  |     { CIPHER_NAME("DH-DSS"), SEC_OID_TLS_DH_DSS, NSS_USE_ALG_IN_SSL_KX }, | 
436  |  |     { CIPHER_NAME("ECDHE-ECDSA"), SEC_OID_TLS_ECDHE_ECDSA, NSS_USE_ALG_IN_SSL_KX }, | 
437  |  |     { CIPHER_NAME("ECDHE-RSA"), SEC_OID_TLS_ECDHE_RSA, NSS_USE_ALG_IN_SSL_KX }, | 
438  |  |     { CIPHER_NAME("ECDH-ECDSA"), SEC_OID_TLS_ECDH_ECDSA, NSS_USE_ALG_IN_SSL_KX }, | 
439  |  |     { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX }, | 
440  |  |     { CIPHER_NAME("TLS-REQUIRE-EMS"), SEC_OID_TLS_REQUIRE_EMS, NSS_USE_ALG_IN_SSL_KX }, | 
441  |  |  | 
442  |  | };  | 
443  |  |  | 
444  |  | static const oidValDef smimeKxOptList[] = { | 
445  |  |     /* Key exchange */  | 
446  |  |     { CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX }, | 
447  |  |     { CIPHER_NAME("RSA-OAEP"), SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX }, | 
448  |  |     { CIPHER_NAME("ECDH"), SEC_OID_ECDH_KEA, NSS_USE_ALG_IN_SMIME_KX }, | 
449  |  |     { CIPHER_NAME("DH"), SEC_OID_X942_DIFFIE_HELMAN_KEY, NSS_USE_ALG_IN_SMIME_KX }, | 
450  |  | };  | 
451  |  |  | 
452  |  | static const oidValDef signOptList[] = { | 
453  |  |     /* Signatures */  | 
454  |  |     { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE, | 
455  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },  | 
456  |  |     { CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION, | 
457  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },  | 
458  |  |     { CIPHER_NAME("RSA-PSS"), SEC_OID_PKCS1_RSA_PSS_SIGNATURE, | 
459  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },  | 
460  |  |     { CIPHER_NAME("ECDSA"), SEC_OID_ANSIX962_EC_PUBLIC_KEY, | 
461  |  |       NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },  | 
462  |  |     { CIPHER_NAME("ED25519"), SEC_OID_ED25519_PUBLIC_KEY, | 
463  |  |       NSS_USE_ALG_IN_SIGNATURE },  | 
464  |  | };  | 
465  |  |  | 
466  |  | typedef struct { | 
467  |  |     const oidValDef *list;  | 
468  |  |     PRUint32 entries;  | 
469  |  |     const char *description;  | 
470  |  |     PRBool allowEmpty;  | 
471  |  | } algListsDef;  | 
472  |  |  | 
473  |  | static const algListsDef algOptLists[] = { | 
474  |  |     { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE }, | 
475  |  |     { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE }, | 
476  |  |     { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE }, | 
477  |  |     { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE }, | 
478  |  |     { kxOptList, PR_ARRAY_SIZE(kxOptList), "SSL-KX", PR_FALSE }, | 
479  |  |     { smimeKxOptList, PR_ARRAY_SIZE(smimeKxOptList), "SMIME-KX", PR_TRUE }, | 
480  |  |     { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_FALSE }, | 
481  |  | };  | 
482  |  |  | 
483  |  | static const optionFreeDef sslOptList[] = { | 
484  |  |     /* Versions */  | 
485  |  |     { CIPHER_NAME("SSL2.0"), 0x002 }, | 
486  |  |     { CIPHER_NAME("SSL3.0"), 0x300 }, | 
487  |  |     { CIPHER_NAME("SSL3.1"), 0x301 }, | 
488  |  |     { CIPHER_NAME("TLS1.0"), 0x301 }, | 
489  |  |     { CIPHER_NAME("TLS1.1"), 0x302 }, | 
490  |  |     { CIPHER_NAME("TLS1.2"), 0x303 }, | 
491  |  |     { CIPHER_NAME("TLS1.3"), 0x304 }, | 
492  |  |     { CIPHER_NAME("DTLS1.0"), 0x302 }, | 
493  |  |     { CIPHER_NAME("DTLS1.1"), 0x302 }, | 
494  |  |     { CIPHER_NAME("DTLS1.2"), 0x303 }, | 
495  |  |     { CIPHER_NAME("DTLS1.3"), 0x304 }, | 
496  |  | };  | 
497  |  |  | 
498  |  | static const optionFreeDef keySizeFlagsList[] = { | 
499  |  |     { CIPHER_NAME("KEY-SIZE-SSL"), NSS_KEY_SIZE_POLICY_SSL_FLAG }, | 
500  |  |     { CIPHER_NAME("KEY-SIZE-SIGN"), NSS_KEY_SIZE_POLICY_SIGN_FLAG }, | 
501  |  |     { CIPHER_NAME("KEY-SIZE-VERIFY"), NSS_KEY_SIZE_POLICY_VERIFY_FLAG }, | 
502  |  |     { CIPHER_NAME("KEY-SIZE-SMIME"), NSS_KEY_SIZE_POLICY_SMIME_FLAG }, | 
503  |  |     { CIPHER_NAME("KEY-SIZE-ALL"), NSS_KEY_SIZE_POLICY_ALL_FLAGS }, | 
504  |  | };  | 
505  |  |  | 
506  |  | static const optionFreeDef freeOptList[] = { | 
507  |  |  | 
508  |  |     /* Restrictions for asymetric keys */  | 
509  |  |     { CIPHER_NAME("RSA-MIN"), NSS_RSA_MIN_KEY_SIZE }, | 
510  |  |     { CIPHER_NAME("DH-MIN"), NSS_DH_MIN_KEY_SIZE }, | 
511  |  |     { CIPHER_NAME("DSA-MIN"), NSS_DSA_MIN_KEY_SIZE }, | 
512  |  |     { CIPHER_NAME("ECC-MIN"), NSS_ECC_MIN_KEY_SIZE }, | 
513  |  |     /* what operations doe the key size apply to */  | 
514  |  |     { CIPHER_NAME("KEY-SIZE-FLAGS"), NSS_KEY_SIZE_POLICY_FLAGS }, | 
515  |  |     /* constraints on SSL Protocols */  | 
516  |  |     { CIPHER_NAME("TLS-VERSION-MIN"), NSS_TLS_VERSION_MIN_POLICY }, | 
517  |  |     { CIPHER_NAME("TLS-VERSION-MAX"), NSS_TLS_VERSION_MAX_POLICY }, | 
518  |  |     /* constraints on DTLS Protocols */  | 
519  |  |     { CIPHER_NAME("DTLS-VERSION-MIN"), NSS_DTLS_VERSION_MIN_POLICY }, | 
520  |  |     { CIPHER_NAME("DTLS-VERSION-MAX"), NSS_DTLS_VERSION_MAX_POLICY } | 
521  |  | };  | 
522  |  |  | 
523  |  | static const policyFlagDef policyFlagList[] = { | 
524  |  |     { CIPHER_NAME("SSL"), NSS_USE_ALG_IN_SSL }, | 
525  |  |     { CIPHER_NAME("SSL-KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX }, | 
526  |  |     /* add other key exhanges in the future */  | 
527  |  |     { CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_KEY_EXCHANGE }, | 
528  |  |     { CIPHER_NAME("CERT-SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE }, | 
529  |  |     { CIPHER_NAME("CMS-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE }, | 
530  |  |     { CIPHER_NAME("SMIME-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE }, | 
531  |  |     { CIPHER_NAME("ALL-SIGNATURE"), NSS_USE_ALG_IN_SIGNATURE }, | 
532  |  |     { CIPHER_NAME("PKCS12"), NSS_USE_ALG_IN_PKCS12 }, | 
533  |  |     /* only use in allow */  | 
534  |  |     { CIPHER_NAME("PKCS12-LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT }, | 
535  |  |     /* only use in disallow */  | 
536  |  |     { CIPHER_NAME("PKCS12-ENCRYPT"), NSS_USE_ALG_IN_PKCS12_ENCRYPT }, | 
537  |  |     { CIPHER_NAME("SMIME"), NSS_USE_ALG_IN_SMIME }, | 
538  |  |     /* only use in allow, enable */  | 
539  |  |     { CIPHER_NAME("SMIME-LEGACY"), NSS_USE_ALG_IN_SMIME_LEGACY }, | 
540  |  |     /* only use in disallow, disable */  | 
541  |  |     { CIPHER_NAME("SMIME-ENCRYPT"), NSS_USE_ALG_IN_SMIME_ENCRYPT }, | 
542  |  |     { CIPHER_NAME("SMIME-KEY-EXCHANGE"), NSS_USE_ALG_IN_SMIME_KX }, | 
543  |  |     /* only use in allow */  | 
544  |  |     { CIPHER_NAME("SMIME-KEY-EXCHANGE-LEGACY"), NSS_USE_ALG_IN_SMIME_KX_LEGACY }, | 
545  |  |     /* only use in disallow */  | 
546  |  |     { CIPHER_NAME("SMIME-KEY-EXCHANGE-ENCRYPT"), NSS_USE_ALG_IN_SMIME_KX_ENCRYPT }, | 
547  |  |     /* sign turns off all signatures, but doesn't change the  | 
548  |  |      * allowance for specific signatures... for example:  | 
549  |  |      *     disallow=sha256/all allow=sha256/signature  | 
550  |  |      * doesn't allow cert-signatures or sime-signatures, where  | 
551  |  |      *     disallow=sha256/all allow=sha256/all-signature  | 
552  |  |      * does. however,  | 
553  |  |      *     disallow=sha256/signature  | 
554  |  |      * and  | 
555  |  |      *     disallow=sha256/all-signature  | 
556  |  |      * are equivalent in effect */  | 
557  |  |     { CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_ANY_SIGNATURE }, | 
558  |  |     /* enable/allow algorithms for legacy (read/verify)operations */  | 
559  |  |     { CIPHER_NAME("LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT | | 
560  |  |                                  NSS_USE_ALG_IN_SMIME_LEGACY |  | 
561  |  |                                  NSS_USE_ALG_IN_SMIME_KX_LEGACY },  | 
562  |  |     /* enable/disable everything */  | 
563  |  |     { CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX | | 
564  |  |                               NSS_USE_ALG_IN_PKCS12 | NSS_USE_ALG_IN_SMIME |  | 
565  |  |                               NSS_USE_ALG_IN_SIGNATURE |  | 
566  |  |                               NSS_USE_ALG_IN_SMIME_KX },  | 
567  |  |     { CIPHER_NAME("NONE"), 0 } | 
568  |  | };  | 
569  |  |  | 
570  |  | /*  | 
571  |  |  *  Get the next cipher on the list. point to the next one in 'next'.  | 
572  |  |  *  return the length;  | 
573  |  |  */  | 
574  |  | static const char *  | 
575  |  | secmod_ArgGetSubValue(const char *cipher, char sep1, char sep2,  | 
576  |  |                       int *len, const char **next)  | 
577  | 0  | { | 
578  | 0  |     const char *start = cipher;  | 
579  |  | 
  | 
580  | 0  |     if (start == NULL) { | 
581  | 0  |         *len = 0;  | 
582  | 0  |         *next = NULL;  | 
583  | 0  |         return start;  | 
584  | 0  |     }  | 
585  |  |  | 
586  | 0  |     for (; *cipher && *cipher != sep2; cipher++) { | 
587  | 0  |         if (*cipher == sep1) { | 
588  | 0  |             *next = cipher + 1;  | 
589  | 0  |             *len = cipher - start;  | 
590  | 0  |             return start;  | 
591  | 0  |         }  | 
592  | 0  |     }  | 
593  | 0  |     *next = NULL;  | 
594  | 0  |     *len = cipher - start;  | 
595  | 0  |     return start;  | 
596  | 0  | }  | 
597  |  |  | 
598  |  | static PRUint32  | 
599  |  | secmod_parsePolicyValue(const char *policyFlags, int policyLength,  | 
600  |  |                         PRBool printPolicyFeedback, PRUint32 policyCheckFlags)  | 
601  | 0  | { | 
602  | 0  |     const char *flag, *currentString;  | 
603  | 0  |     PRUint32 flags = 0;  | 
604  | 0  |     int i;  | 
605  |  | 
  | 
606  | 0  |     for (currentString = policyFlags; currentString &&  | 
607  | 0  |                                       currentString < policyFlags + policyLength;) { | 
608  | 0  |         int length;  | 
609  | 0  |         PRBool unknown = PR_TRUE;  | 
610  | 0  |         flag = secmod_ArgGetSubValue(currentString, ',', ':', &length,  | 
611  | 0  |                                      ¤tString);  | 
612  | 0  |         if (length == 0) { | 
613  | 0  |             continue;  | 
614  | 0  |         }  | 
615  | 0  |         for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) { | 
616  | 0  |             const policyFlagDef *policy = &policyFlagList[i];  | 
617  | 0  |             unsigned name_size = policy->name_size;  | 
618  | 0  |             if ((policy->name_size == length) &&  | 
619  | 0  |                 PORT_Strncasecmp(policy->name, flag, name_size) == 0) { | 
620  | 0  |                 flags |= policy->flag;  | 
621  | 0  |                 unknown = PR_FALSE;  | 
622  | 0  |                 break;  | 
623  | 0  |             }  | 
624  | 0  |         }  | 
625  | 0  |         if (unknown && printPolicyFeedback &&  | 
626  | 0  |             (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) { | 
627  | 0  |             PR_SetEnv("NSS_POLICY_FAIL=1"); | 
628  | 0  |             fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",  | 
629  | 0  |                     policyLength, policyFlags, length, flag);  | 
630  | 0  |         }  | 
631  | 0  |     }  | 
632  | 0  |     return flags;  | 
633  | 0  | }  | 
634  |  |  | 
635  |  | /* allow symbolic names for values. The only ones currently defines or  | 
636  |  |  * SSL protocol versions. */  | 
637  |  | static SECStatus  | 
638  |  | secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,  | 
639  |  |                          PRInt32 *result)  | 
640  | 0  | { | 
641  | 0  |     PRInt32 val = atoi(policyValue);  | 
642  | 0  |     int i;  | 
643  |  | 
  | 
644  | 0  |     if ((val != 0) || (*policyValue == '0')) { | 
645  | 0  |         *result = val;  | 
646  | 0  |         return SECSuccess;  | 
647  | 0  |     }  | 
648  | 0  |     if (policyValueLength == 0) { | 
649  | 0  |         return SECFailure;  | 
650  | 0  |     }  | 
651  |  |     /* handle any ssl strings */  | 
652  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) { | 
653  | 0  |         if (policyValueLength == sslOptList[i].name_size &&  | 
654  | 0  |             PORT_Strncasecmp(sslOptList[i].name, policyValue,  | 
655  | 0  |                              sslOptList[i].name_size) == 0) { | 
656  | 0  |             *result = sslOptList[i].option;  | 
657  | 0  |             return SECSuccess;  | 
658  | 0  |         }  | 
659  | 0  |     }  | 
660  |  |     /* handle key_size flags. Each flag represents a bit, which  | 
661  |  |      * gets or'd together. They can be separated by , | or + */  | 
662  | 0  |     val = 0;  | 
663  | 0  |     while (policyValueLength > 0) { | 
664  | 0  |         PRBool found = PR_FALSE;  | 
665  | 0  |         for (i = 0; i < PR_ARRAY_SIZE(keySizeFlagsList); i++) { | 
666  | 0  |             if (PORT_Strncasecmp(keySizeFlagsList[i].name, policyValue,  | 
667  | 0  |                                  keySizeFlagsList[i].name_size) == 0) { | 
668  | 0  |                 val |= keySizeFlagsList[i].option;  | 
669  | 0  |                 found = PR_TRUE;  | 
670  | 0  |                 policyValue += keySizeFlagsList[i].name_size;  | 
671  | 0  |                 policyValueLength -= keySizeFlagsList[i].name_size;  | 
672  | 0  |                 break;  | 
673  | 0  |             }  | 
674  | 0  |         }  | 
675  | 0  |         if (!found) { | 
676  | 0  |             return SECFailure;  | 
677  | 0  |         }  | 
678  | 0  |         if (*policyValue == ',' || *policyValue == '|' || *policyValue == '+') { | 
679  | 0  |             policyValue++;  | 
680  | 0  |             policyValueLength--;  | 
681  | 0  |         }  | 
682  | 0  |     }  | 
683  | 0  |     *result = val;  | 
684  | 0  |     return SECSuccess;  | 
685  | 0  | }  | 
686  |  |  | 
687  |  | /* Policy operations:  | 
688  |  |  *     Disallow: operation is disallowed by policy. Implies disabled.  | 
689  |  |  *     Allow: operation is allowed by policy (but could be disabled).  | 
690  |  |  *     Disable: operation is turned off by default (but could be allowed).  | 
691  |  |  *     Enable: operation is enabled by default. Implies allowed.  | 
692  |  |  */  | 
693  |  | typedef enum { | 
694  |  |     NSS_DISALLOW,  | 
695  |  |     NSS_ALLOW,  | 
696  |  |     NSS_DISABLE,  | 
697  |  |     NSS_ENABLE  | 
698  |  | } NSSPolicyOperation;  | 
699  |  |  | 
700  |  | /* Enable/Disable only apply to SSL cipher suites and S/MIME symetric algorithms.  | 
701  |  |  * Enable/Disable is implemented by clearing the DEFAULT_NOT_VALID  | 
702  |  |  * flag, then setting the NSS_USE_DEFAULT_SSL_ENABLE and  | 
703  |  |  * NSS_USE_DEFAULT_SMIME_ENABLE flags to the correct value. The ssl  | 
704  |  |  * policy code will then sort out what to set based on ciphers and  | 
705  |  |  * cipher suite values and the smime policy code will sort  | 
706  |  |  * out which ciphers to include in capabilities based on these values */  | 
707  |  | static SECStatus  | 
708  |  | secmod_setDefault(SECOidTag oid, NSSPolicyOperation operation,  | 
709  |  |                   PRUint32 value)  | 
710  | 0  | { | 
711  | 0  |     SECStatus rv = SECSuccess;  | 
712  | 0  |     PRUint32 policy;  | 
713  | 0  |     PRUint32 useDefault = 0;  | 
714  | 0  |     PRUint32 set = 0;  | 
715  |  |     /* we always clear the default not valid flag as this operation will  | 
716  |  |      * make the defaults valid */  | 
717  | 0  |     PRUint32 clear = NSS_USE_DEFAULT_NOT_VALID;  | 
718  |  |  | 
719  |  |     /* what values are we trying to change */  | 
720  |  |     /* if either SSL or SSL_KX is set, enable SSL */  | 
721  | 0  |     if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) { | 
722  | 0  |         useDefault |= NSS_USE_DEFAULT_SSL_ENABLE;  | 
723  | 0  |     }  | 
724  |  |     /* only bulk ciphers are configured as enable in S/MIME, only  | 
725  |  |      * enable them if both SMIME bits are set */  | 
726  | 0  |     if ((value & NSS_USE_ALG_IN_SMIME) == NSS_USE_ALG_IN_SMIME) { | 
727  | 0  |         useDefault |= NSS_USE_DEFAULT_SMIME_ENABLE;  | 
728  | 0  |     }  | 
729  |  |  | 
730  |  |     /* on disable we clear, on enable we set */  | 
731  | 0  |     if (operation == NSS_DISABLE) { | 
732  | 0  |         clear |= useDefault;  | 
733  | 0  |     } else { | 
734  |  |         /* we also turn the cipher on by policy if we enable it,  | 
735  |  |          * so include the policy bits */  | 
736  | 0  |         set |= value | useDefault;  | 
737  | 0  |     }  | 
738  |  |  | 
739  |  |     /* if we haven't set the not valid flag yet, then we need to  | 
740  |  |      * clear any of the other bits we aren't actually setting as well.  | 
741  |  |      */  | 
742  | 0  |     rv = NSS_GetAlgorithmPolicy(oid, &policy);  | 
743  | 0  |     if (rv != SECSuccess) { | 
744  | 0  |         return rv;  | 
745  | 0  |     }  | 
746  | 0  |     if (policy & NSS_USE_DEFAULT_NOT_VALID) { | 
747  | 0  |         clear |= ((NSS_USE_DEFAULT_SSL_ENABLE | NSS_USE_DEFAULT_SMIME_ENABLE) &  | 
748  | 0  |                   ~set);  | 
749  | 0  |     }  | 
750  | 0  |     return NSS_SetAlgorithmPolicy(oid, set, clear);  | 
751  | 0  | }  | 
752  |  |  | 
753  |  | /* apply the operator specific policy */  | 
754  |  | SECStatus  | 
755  |  | secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation,  | 
756  |  |                           PRUint32 value)  | 
757  | 0  | { | 
758  | 0  |     SECStatus rv = SECSuccess;  | 
759  | 0  |     switch (operation) { | 
760  | 0  |         case NSS_DISALLOW:  | 
761  |  |             /* clear the requested policy bits */  | 
762  | 0  |             rv = NSS_SetAlgorithmPolicy(oid, 0, value);  | 
763  | 0  |             break;  | 
764  | 0  |         case NSS_ALLOW:  | 
765  |  |             /* set the requested policy bits */  | 
766  | 0  |             rv = NSS_SetAlgorithmPolicy(oid, value, 0);  | 
767  | 0  |             break;  | 
768  | 0  |         case NSS_DISABLE:  | 
769  | 0  |         case NSS_ENABLE:  | 
770  | 0  |             rv = secmod_setDefault(oid, operation, value);  | 
771  | 0  |             break;  | 
772  | 0  |         default:  | 
773  | 0  |             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);  | 
774  | 0  |             rv = SECFailure;  | 
775  | 0  |             break;  | 
776  | 0  |     }  | 
777  | 0  |     return rv;  | 
778  | 0  | }  | 
779  |  |  | 
780  |  | const char *  | 
781  |  | secmod_getOperationString(NSSPolicyOperation operation)  | 
782  | 0  | { | 
783  | 0  |     switch (operation) { | 
784  | 0  |         case NSS_DISALLOW:  | 
785  | 0  |             return "disallow";  | 
786  | 0  |         case NSS_ALLOW:  | 
787  | 0  |             return "allow";  | 
788  | 0  |         case NSS_DISABLE:  | 
789  | 0  |             return "disable";  | 
790  | 0  |         case NSS_ENABLE:  | 
791  | 0  |             return "enable";  | 
792  | 0  |         default:  | 
793  | 0  |             break;  | 
794  | 0  |     }  | 
795  | 0  |     return "invalid";  | 
796  | 0  | }  | 
797  |  |  | 
798  |  | /* Allow external applications fetch the policy oid based on the internal  | 
799  |  |  * string mapping used by the configuration system. The search can be  | 
800  |  |  * narrowed by supplying the name of the table (list) that the policy  | 
801  |  |  * is on. The value 'Any' allows the policy to be searched on all lists */  | 
802  |  | SECOidTag  | 
803  |  | SECMOD_PolicyStringToOid(const char *policy, const char *list)  | 
804  | 0  | { | 
805  | 0  |     PRBool any = (PORT_Strcasecmp(list, "Any") == 0) ? PR_TRUE : PR_FALSE;  | 
806  | 0  |     int len = PORT_Strlen(policy);  | 
807  | 0  |     int i, j;  | 
808  |  | 
  | 
809  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { | 
810  | 0  |         const algListsDef *algOptList = &algOptLists[i];  | 
811  | 0  |         if (any || (PORT_Strcasecmp(algOptList->description, list) == 0)) { | 
812  | 0  |             for (j = 0; j < algOptList->entries; j++) { | 
813  | 0  |                 const oidValDef *algOpt = &algOptList->list[j];  | 
814  | 0  |                 unsigned name_size = algOpt->name_size;  | 
815  | 0  |                 if (len == name_size &&  | 
816  | 0  |                     PORT_Strcasecmp(algOpt->name, policy) == 0) { | 
817  | 0  |                     return algOpt->oid;  | 
818  | 0  |                 }  | 
819  | 0  |             }  | 
820  | 0  |         }  | 
821  | 0  |     }  | 
822  | 0  |     return SEC_OID_UNKNOWN;  | 
823  | 0  | }  | 
824  |  |  | 
825  |  | /* Allow external applications fetch the NSS option based on the internal  | 
826  |  |  * string mapping used by the configuration system. */  | 
827  |  | PRUint32  | 
828  |  | SECMOD_PolicyStringToOpt(const char *policy)  | 
829  | 0  | { | 
830  | 0  |     int len = PORT_Strlen(policy);  | 
831  | 0  |     int i;  | 
832  |  | 
  | 
833  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) { | 
834  | 0  |         const optionFreeDef *freeOpt = &freeOptList[i];  | 
835  | 0  |         unsigned name_size = freeOpt->name_size;  | 
836  | 0  |         if (len == name_size &&  | 
837  | 0  |             PORT_Strcasecmp(freeOpt->name, policy) == 0) { | 
838  | 0  |             return freeOpt->option;  | 
839  | 0  |         }  | 
840  | 0  |     }  | 
841  | 0  |     return 0;  | 
842  | 0  | }  | 
843  |  |  | 
844  |  | /* Allow external applications map policy flags to their string equivalance.  | 
845  |  |  * Some strings represent more than one flag. If more than one flag is included  | 
846  |  |  * the returned string is the string that contains any of the  | 
847  |  |  * supplied flags unless exact is specified. If exact is specified, then the  | 
848  |  |  * returned value matches all the included flags and only those flags. For  | 
849  |  |  * Example: 'ALL-SIGNATURE' has the bits NSS_USE_ALG_IN_CERTSIGNATURE|  | 
850  |  |  * NSS_USE_ALG_IN_SMIME_SIGNATURE|NSS_USE_ALG_IN_ANY_SIGNATURE. If you ask for  | 
851  |  |  * NSS_USE_ALG_IN_CERT_SIGNATURE|NSS_USE_ALG_IN_SMIME_SIGNATURE and don't set  | 
852  |  |  * exact, this function will return 'ALL-SIGNATURE' if you do set exact, you must  | 
853  |  |  * include all three bits in value to get 'All-SIGNATURE'*/  | 
854  |  | const char *  | 
855  |  | SECMOD_FlagsToPolicyString(PRUint32 val, PRBool exact)  | 
856  | 0  | { | 
857  | 0  |     int i;  | 
858  |  | 
  | 
859  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) { | 
860  | 0  |         const policyFlagDef *policy = &policyFlagList[i];  | 
861  | 0  |         if (exact && (policy->flag == val)) { | 
862  | 0  |             return policy->name;  | 
863  | 0  |         }  | 
864  | 0  |         if (!exact && ((policy->flag & val) == policy->flag)) { | 
865  | 0  |             return policy->name;  | 
866  | 0  |         }  | 
867  | 0  |     }  | 
868  | 0  |     return NULL;  | 
869  | 0  | }  | 
870  |  |  | 
871  |  | static SECStatus  | 
872  |  | secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,  | 
873  |  |                          PRBool printPolicyFeedback, PRUint32 policyCheckFlags)  | 
874  | 0  | { | 
875  | 0  |     const char *cipher, *currentString;  | 
876  | 0  |     unsigned i, j;  | 
877  | 0  |     SECStatus rv = SECSuccess;  | 
878  | 0  |     PRBool unknown;  | 
879  |  | 
  | 
880  | 0  |     if (policyString == NULL || policyString[0] == 0) { | 
881  | 0  |         return SECSuccess; /* do nothing */  | 
882  | 0  |     }  | 
883  |  |  | 
884  |  |     /* if we change any of these, make sure it gets applied in ssl as well */  | 
885  | 0  |     NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0);  | 
886  |  | 
  | 
887  | 0  |     for (currentString = policyString; currentString;) { | 
888  | 0  |         int length;  | 
889  | 0  |         PRBool newValue = PR_FALSE;  | 
890  |  | 
  | 
891  | 0  |         cipher = secmod_ArgGetSubValue(currentString, ':', 0, &length,  | 
892  | 0  |                                        ¤tString);  | 
893  | 0  |         unknown = PR_TRUE;  | 
894  | 0  |         if (length >= 3 && cipher[3] == '/') { | 
895  | 0  |             newValue = PR_TRUE;  | 
896  | 0  |         }  | 
897  | 0  |         if ((newValue || (length == 3)) && PORT_Strncasecmp(cipher, "all", 3) == 0) { | 
898  |  |             /* disable or enable all options by default */  | 
899  | 0  |             PRUint32 value = 0;  | 
900  | 0  |             if (newValue) { | 
901  | 0  |                 value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback, policyCheckFlags);  | 
902  | 0  |             }  | 
903  | 0  |             for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { | 
904  | 0  |                 const algListsDef *algOptList = &algOptLists[i];  | 
905  | 0  |                 for (j = 0; j < algOptList->entries; j++) { | 
906  | 0  |                     if (!newValue) { | 
907  | 0  |                         value = algOptList->list[j].val;  | 
908  | 0  |                     }  | 
909  | 0  |                     secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);  | 
910  | 0  |                 }  | 
911  | 0  |             }  | 
912  | 0  |             continue;  | 
913  | 0  |         }  | 
914  |  |  | 
915  | 0  |         for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { | 
916  | 0  |             const algListsDef *algOptList = &algOptLists[i];  | 
917  | 0  |             for (j = 0; j < algOptList->entries; j++) { | 
918  | 0  |                 const oidValDef *algOpt = &algOptList->list[j];  | 
919  | 0  |                 unsigned name_size = algOpt->name_size;  | 
920  | 0  |                 PRBool newOption = PR_FALSE;  | 
921  |  | 
  | 
922  | 0  |                 if ((length >= name_size) && (cipher[name_size] == '/')) { | 
923  | 0  |                     newOption = PR_TRUE;  | 
924  | 0  |                 }  | 
925  | 0  |                 if ((newOption || algOpt->name_size == length) &&  | 
926  | 0  |                     PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) { | 
927  | 0  |                     PRUint32 value = algOpt->val;  | 
928  | 0  |                     if (newOption) { | 
929  | 0  |                         value = secmod_parsePolicyValue(&cipher[name_size] + 1,  | 
930  | 0  |                                                         length - name_size - 1,  | 
931  | 0  |                                                         printPolicyFeedback,  | 
932  | 0  |                                                         policyCheckFlags);  | 
933  | 0  |                     }  | 
934  | 0  |                     rv = secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);  | 
935  | 0  |                     if (rv != SECSuccess) { | 
936  |  |                         /* could not enable option */  | 
937  |  |                         /* NSS_SetAlgorithPolicy should have set the error code */  | 
938  | 0  |                         return SECFailure;  | 
939  | 0  |                     }  | 
940  | 0  |                     unknown = PR_FALSE;  | 
941  | 0  |                     break;  | 
942  | 0  |                 }  | 
943  | 0  |             }  | 
944  | 0  |         }  | 
945  | 0  |         if (!unknown) { | 
946  | 0  |             continue;  | 
947  | 0  |         }  | 
948  |  |  | 
949  | 0  |         for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) { | 
950  | 0  |             const optionFreeDef *freeOpt = &freeOptList[i];  | 
951  | 0  |             unsigned name_size = freeOpt->name_size;  | 
952  |  | 
  | 
953  | 0  |             if ((length > name_size) && cipher[name_size] == '=' &&  | 
954  | 0  |                 PORT_Strncasecmp(freeOpt->name, cipher, name_size) == 0) { | 
955  | 0  |                 PRInt32 val;  | 
956  | 0  |                 const char *policyValue = &cipher[name_size + 1];  | 
957  | 0  |                 int policyValueLength = length - name_size - 1;  | 
958  | 0  |                 rv = secmod_getPolicyOptValue(policyValue, policyValueLength,  | 
959  | 0  |                                               &val);  | 
960  | 0  |                 if (rv != SECSuccess) { | 
961  | 0  |                     if (printPolicyFeedback &&  | 
962  | 0  |                         (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) { | 
963  | 0  |                         PR_SetEnv("NSS_POLICY_FAIL=1"); | 
964  | 0  |                         fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",  | 
965  | 0  |                                 length, cipher, policyValueLength, policyValue);  | 
966  | 0  |                     }  | 
967  | 0  |                     return SECFailure;  | 
968  | 0  |                 }  | 
969  | 0  |                 rv = NSS_OptionSet(freeOpt->option, val);  | 
970  | 0  |                 if (rv != SECSuccess) { | 
971  |  |                     /* could not enable option */  | 
972  |  |                     /* NSS_OptionSet should have set the error code */  | 
973  | 0  |                     return SECFailure;  | 
974  | 0  |                 }  | 
975  |  |                 /* to allow the policy to expand in the future. ignore ciphers  | 
976  |  |                  * we don't understand */  | 
977  | 0  |                 unknown = PR_FALSE;  | 
978  | 0  |                 break;  | 
979  | 0  |             }  | 
980  | 0  |         }  | 
981  |  |  | 
982  | 0  |         if (unknown && printPolicyFeedback &&  | 
983  | 0  |             (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER)) { | 
984  | 0  |             PR_SetEnv("NSS_POLICY_FAIL=1"); | 
985  | 0  |             fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n",  | 
986  | 0  |                     secmod_getOperationString(operation), length, cipher);  | 
987  | 0  |         }  | 
988  | 0  |     }  | 
989  | 0  |     return rv;  | 
990  | 0  | }  | 
991  |  |  | 
992  |  | static void  | 
993  |  | secmod_sanityCheckCryptoPolicy(void)  | 
994  | 0  | { | 
995  | 0  |     unsigned i, j;  | 
996  | 0  |     SECStatus rv = SECSuccess;  | 
997  | 0  |     unsigned num_kx_enabled = 0;  | 
998  | 0  |     unsigned num_ssl_enabled = 0;  | 
999  | 0  |     unsigned num_sig_enabled = 0;  | 
1000  | 0  |     unsigned enabledCount[PR_ARRAY_SIZE(algOptLists)];  | 
1001  | 0  |     const char *sWarn = "WARN";  | 
1002  | 0  |     const char *sInfo = "INFO";  | 
1003  | 0  |     PRBool haveWarning = PR_FALSE;  | 
1004  |  | 
  | 
1005  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { | 
1006  | 0  |         const algListsDef *algOptList = &algOptLists[i];  | 
1007  | 0  |         enabledCount[i] = 0;  | 
1008  | 0  |         for (j = 0; j < algOptList->entries; j++) { | 
1009  | 0  |             const oidValDef *algOpt = &algOptList->list[j];  | 
1010  | 0  |             PRUint32 value;  | 
1011  | 0  |             PRBool anyEnabled = PR_FALSE;  | 
1012  | 0  |             rv = NSS_GetAlgorithmPolicy(algOpt->oid, &value);  | 
1013  | 0  |             if (rv != SECSuccess) { | 
1014  | 0  |                 PR_SetEnv("NSS_POLICY_FAIL=1"); | 
1015  | 0  |                 fprintf(stderr, "NSS-POLICY-FAIL: internal failure with NSS_GetAlgorithmPolicy at %u\n", i);  | 
1016  | 0  |                 return;  | 
1017  | 0  |             }  | 
1018  |  |  | 
1019  | 0  |             if ((algOpt->val & NSS_USE_ALG_IN_SSL_KX) && (value & NSS_USE_ALG_IN_SSL_KX)) { | 
1020  | 0  |                 ++num_kx_enabled;  | 
1021  | 0  |                 anyEnabled = PR_TRUE;  | 
1022  | 0  |                 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL-KX\n", algOpt->name);  | 
1023  | 0  |             }  | 
1024  | 0  |             if ((algOpt->val & NSS_USE_ALG_IN_SSL) && (value & NSS_USE_ALG_IN_SSL)) { | 
1025  | 0  |                 ++num_ssl_enabled;  | 
1026  | 0  |                 anyEnabled = PR_TRUE;  | 
1027  | 0  |                 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL\n", algOpt->name);  | 
1028  | 0  |             }  | 
1029  | 0  |             if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) &&  | 
1030  | 0  |                 ((value & NSS_USE_CERT_SIGNATURE_OK) == NSS_USE_CERT_SIGNATURE_OK)) { | 
1031  | 0  |                 ++num_sig_enabled;  | 
1032  | 0  |                 anyEnabled = PR_TRUE;  | 
1033  | 0  |                 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for CERT-SIGNATURE\n", algOpt->name);  | 
1034  | 0  |             }  | 
1035  | 0  |             if (anyEnabled) { | 
1036  | 0  |                 ++enabledCount[i];  | 
1037  | 0  |             }  | 
1038  | 0  |         }  | 
1039  | 0  |     }  | 
1040  | 0  |     fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG-KX: %u\n", num_kx_enabled ? sInfo : sWarn, num_kx_enabled);  | 
1041  | 0  |     fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG: %u\n", num_ssl_enabled ? sInfo : sWarn, num_ssl_enabled);  | 
1042  | 0  |     fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CERT-SIG: %u\n", num_sig_enabled ? sInfo : sWarn, num_sig_enabled);  | 
1043  | 0  |     if (!num_kx_enabled || !num_ssl_enabled || !num_sig_enabled) { | 
1044  | 0  |         haveWarning = PR_TRUE;  | 
1045  | 0  |     }  | 
1046  | 0  |     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { | 
1047  | 0  |         const algListsDef *algOptList = &algOptLists[i];  | 
1048  | 0  |         fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);  | 
1049  | 0  |         if (!enabledCount[i] && !algOptList->allowEmpty) { | 
1050  | 0  |             haveWarning = PR_TRUE;  | 
1051  | 0  |         }  | 
1052  | 0  |     }  | 
1053  | 0  |     if (haveWarning) { | 
1054  | 0  |         PR_SetEnv("NSS_POLICY_WARN=1"); | 
1055  | 0  |     }  | 
1056  | 0  | }  | 
1057  |  |  | 
1058  |  | static SECStatus  | 
1059  |  | secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback,  | 
1060  |  |                          PRUint32 policyCheckFlags)  | 
1061  | 2  | { | 
1062  | 2  |     char *args;  | 
1063  | 2  |     SECStatus rv;  | 
1064  |  |  | 
1065  | 2  |     if (policyConfig == NULL) { | 
1066  | 2  |         return SECSuccess; /* no policy given */  | 
1067  | 2  |     }  | 
1068  |  |     /* make sure we initialize the oid table and set all the default policy  | 
1069  |  |      * values first so we can override them here */  | 
1070  | 0  |     rv = SECOID_Init();  | 
1071  | 0  |     if (rv != SECSuccess) { | 
1072  | 0  |         return rv;  | 
1073  | 0  |     }  | 
1074  | 0  |     args = NSSUTIL_ArgGetParamValue("disallow", policyConfig); | 
1075  | 0  |     rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback,  | 
1076  | 0  |                                   policyCheckFlags);  | 
1077  | 0  |     if (args)  | 
1078  | 0  |         PORT_Free(args);  | 
1079  | 0  |     if (rv != SECSuccess) { | 
1080  | 0  |         return rv;  | 
1081  | 0  |     }  | 
1082  | 0  |     args = NSSUTIL_ArgGetParamValue("allow", policyConfig); | 
1083  | 0  |     rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback,  | 
1084  | 0  |                                   policyCheckFlags);  | 
1085  | 0  |     if (args)  | 
1086  | 0  |         PORT_Free(args);  | 
1087  | 0  |     if (rv != SECSuccess) { | 
1088  | 0  |         return rv;  | 
1089  | 0  |     }  | 
1090  | 0  |     args = NSSUTIL_ArgGetParamValue("disable", policyConfig); | 
1091  | 0  |     rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback,  | 
1092  | 0  |                                   policyCheckFlags);  | 
1093  | 0  |     if (args)  | 
1094  | 0  |         PORT_Free(args);  | 
1095  | 0  |     if (rv != SECSuccess) { | 
1096  | 0  |         return rv;  | 
1097  | 0  |     }  | 
1098  | 0  |     args = NSSUTIL_ArgGetParamValue("enable", policyConfig); | 
1099  | 0  |     rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback,  | 
1100  | 0  |                                   policyCheckFlags);  | 
1101  | 0  |     if (args)  | 
1102  | 0  |         PORT_Free(args);  | 
1103  | 0  |     if (rv != SECSuccess) { | 
1104  | 0  |         return rv;  | 
1105  | 0  |     }  | 
1106  |  |     /* this has to be last. Everything after this will be a noop */  | 
1107  | 0  |     if (NSSUTIL_ArgHasFlag("flags", "ssl-lock", policyConfig)) { | 
1108  | 0  |         PRInt32 locks;  | 
1109  |  |         /* don't overwrite other (future) lock flags */  | 
1110  | 0  |         rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks);  | 
1111  | 0  |         if (rv == SECSuccess) { | 
1112  | 0  |             rv = NSS_OptionSet(NSS_DEFAULT_LOCKS, locks | NSS_DEFAULT_SSL_LOCK);  | 
1113  | 0  |         }  | 
1114  | 0  |         if (rv != SECSuccess) { | 
1115  | 0  |             return rv;  | 
1116  | 0  |         }  | 
1117  | 0  |     }  | 
1118  | 0  |     if (NSSUTIL_ArgHasFlag("flags", "policy-lock", policyConfig)) { | 
1119  | 0  |         NSS_LockPolicy();  | 
1120  | 0  |     }  | 
1121  | 0  |     if (printPolicyFeedback) { | 
1122  |  |         /* This helps to distinguish configurations that don't contain any  | 
1123  |  |          * policy config= statement. */  | 
1124  | 0  |         PR_SetEnv("NSS_POLICY_LOADED=1"); | 
1125  | 0  |         fprintf(stderr, "NSS-POLICY-INFO: LOADED-SUCCESSFULLY\n");  | 
1126  | 0  |         secmod_sanityCheckCryptoPolicy();  | 
1127  | 0  |     }  | 
1128  | 0  |     return rv;  | 
1129  | 0  | }  | 
1130  |  |  | 
1131  |  | static PRUint32  | 
1132  |  | secmod_parsePolicyCheckFlags(const char *nss)  | 
1133  | 4  | { | 
1134  | 4  |     PRUint32 policyCheckFlags = 0;  | 
1135  |  |  | 
1136  | 4  |     if (NSSUTIL_ArgHasFlag("flags", "policyCheckIdentifier", nss)) { | 
1137  | 0  |         policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER;  | 
1138  | 0  |     }  | 
1139  |  |  | 
1140  | 4  |     if (NSSUTIL_ArgHasFlag("flags", "policyCheckValue", nss)) { | 
1141  | 0  |         policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE;  | 
1142  | 0  |     }  | 
1143  |  |  | 
1144  | 4  |     return policyCheckFlags;  | 
1145  | 4  | }  | 
1146  |  |  | 
1147  |  | /*  | 
1148  |  |  * for 3.4 we continue to use the old SECMODModule structure  | 
1149  |  |  */  | 
1150  |  | SECMODModule *  | 
1151  |  | SECMOD_CreateModuleEx(const char *library, const char *moduleName,  | 
1152  |  |                       const char *parameters, const char *nss,  | 
1153  |  |                       const char *config)  | 
1154  | 2  | { | 
1155  | 2  |     SECMODModule *mod;  | 
1156  | 2  |     SECStatus rv;  | 
1157  | 2  |     char *slotParams, *ciphers;  | 
1158  | 2  |     PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss); | 
1159  | 2  |     PRUint32 policyCheckFlags = secmod_parsePolicyCheckFlags(nss);  | 
1160  |  |  | 
1161  | 2  |     rv = secmod_parseCryptoPolicy(config, printPolicyFeedback, policyCheckFlags);  | 
1162  |  |  | 
1163  |  |     /* do not load the module if policy parsing fails */  | 
1164  | 2  |     if (rv != SECSuccess) { | 
1165  | 0  |         if (printPolicyFeedback) { | 
1166  | 0  |             PR_SetEnv("NSS_POLICY_FAIL=1"); | 
1167  | 0  |             fprintf(stderr, "NSS-POLICY-FAIL: policy config parsing failed, not loading module %s\n", moduleName);  | 
1168  | 0  |         }  | 
1169  | 0  |         return NULL;  | 
1170  | 0  |     }  | 
1171  |  |  | 
1172  | 2  |     mod = secmod_NewModule();  | 
1173  | 2  |     if (mod == NULL)  | 
1174  | 0  |         return NULL;  | 
1175  |  |  | 
1176  | 2  |     mod->commonName = PORT_ArenaStrdup(mod->arena, moduleName ? moduleName : "");  | 
1177  | 2  |     if (library) { | 
1178  | 0  |         mod->dllName = PORT_ArenaStrdup(mod->arena, library);  | 
1179  | 0  |     }  | 
1180  |  |     /* new field */  | 
1181  | 2  |     if (parameters) { | 
1182  | 2  |         mod->libraryParams = PORT_ArenaStrdup(mod->arena, parameters);  | 
1183  | 2  |     }  | 
1184  |  |  | 
1185  | 2  |     mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nss); | 
1186  | 2  |     mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nss); | 
1187  |  |     /* if the system FIPS mode is enabled, force FIPS to be on */  | 
1188  | 2  |     if (SECMOD_GetSystemFIPSEnabled()) { | 
1189  | 0  |         mod->isFIPS = PR_TRUE;  | 
1190  | 0  |     }  | 
1191  | 2  |     mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nss); | 
1192  | 2  |     slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss); | 
1193  | 2  |     mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,  | 
1194  | 2  |                                              &mod->slotInfoCount);  | 
1195  | 2  |     if (slotParams)  | 
1196  | 1  |         PORT_Free(slotParams);  | 
1197  |  |     /* new field */  | 
1198  | 2  |     mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nss, | 
1199  | 2  |                                           NSSUTIL_DEFAULT_TRUST_ORDER, NULL);  | 
1200  |  |     /* new field */  | 
1201  | 2  |     mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nss, | 
1202  | 2  |                                            NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);  | 
1203  |  |     /* new field */  | 
1204  | 2  |     mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nss); | 
1205  | 2  |     mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nss); | 
1206  | 2  |     if (mod->moduleDBOnly)  | 
1207  | 1  |         mod->isModuleDB = PR_TRUE;  | 
1208  |  |  | 
1209  |  |     /* we need more bits, but we also want to preserve binary compatibility  | 
1210  |  |      * so we overload the isModuleDB PRBool with additional flags.  | 
1211  |  |      * These flags are only valid if mod->isModuleDB is already set.  | 
1212  |  |      * NOTE: this depends on the fact that PRBool is at least a char on  | 
1213  |  |      * all platforms. These flags are only valid if moduleDB is set, so  | 
1214  |  |      * code checking if (mod->isModuleDB) will continue to work correctly. */  | 
1215  | 2  |     if (mod->isModuleDB) { | 
1216  | 1  |         char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB;  | 
1217  | 1  |         if (NSSUTIL_ArgHasFlag("flags", "skipFirst", nss)) { | 
1218  | 0  |             flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST;  | 
1219  | 0  |         }  | 
1220  | 1  |         if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nss)) { | 
1221  | 1  |             flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB;  | 
1222  | 1  |         }  | 
1223  | 1  |         if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nss)) { | 
1224  | 0  |             flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY;  | 
1225  | 0  |         }  | 
1226  |  |         /* additional moduleDB flags could be added here in the future */  | 
1227  | 1  |         mod->isModuleDB = (PRBool)flags;  | 
1228  | 1  |     }  | 
1229  |  |  | 
1230  | 2  |     if (mod->internal) { | 
1231  | 2  |         char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL;  | 
1232  |  |  | 
1233  | 2  |         if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nss)) { | 
1234  | 1  |             flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;  | 
1235  | 1  |         }  | 
1236  | 2  |         mod->internal = (PRBool)flags;  | 
1237  | 2  |     }  | 
1238  |  |  | 
1239  | 2  |     ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss); | 
1240  | 2  |     NSSUTIL_ArgParseCipherFlags(&mod->ssl[0], ciphers);  | 
1241  | 2  |     if (ciphers)  | 
1242  | 0  |         PORT_Free(ciphers);  | 
1243  |  |  | 
1244  | 2  |     secmod_PrivateModuleCount++;  | 
1245  |  |  | 
1246  | 2  |     return mod;  | 
1247  | 2  | }  | 
1248  |  |  | 
1249  |  | PRBool  | 
1250  |  | SECMOD_GetSkipFirstFlag(SECMODModule *mod)  | 
1251  | 1  | { | 
1252  | 1  |     char flags = (char)mod->isModuleDB;  | 
1253  |  |  | 
1254  | 1  |     return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE;  | 
1255  | 1  | }  | 
1256  |  |  | 
1257  |  | PRBool  | 
1258  |  | SECMOD_GetDefaultModDBFlag(SECMODModule *mod)  | 
1259  | 0  | { | 
1260  | 0  |     char flags = (char)mod->isModuleDB;  | 
1261  |  | 
  | 
1262  | 0  |     return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;  | 
1263  | 0  | }  | 
1264  |  |  | 
1265  |  | PRBool  | 
1266  |  | secmod_PolicyOnly(SECMODModule *mod)  | 
1267  | 2  | { | 
1268  | 2  |     char flags = (char)mod->isModuleDB;  | 
1269  |  |  | 
1270  | 2  |     return (flags & SECMOD_FLAG_MODULE_DB_POLICY_ONLY) ? PR_TRUE : PR_FALSE;  | 
1271  | 2  | }  | 
1272  |  |  | 
1273  |  | PRBool  | 
1274  |  | secmod_IsInternalKeySlot(SECMODModule *mod)  | 
1275  | 3  | { | 
1276  | 3  |     char flags = (char)mod->internal;  | 
1277  |  |  | 
1278  | 3  |     return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE;  | 
1279  | 3  | }  | 
1280  |  |  | 
1281  |  | void  | 
1282  |  | secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val)  | 
1283  | 0  | { | 
1284  | 0  |     char flags = (char)mod->internal;  | 
1285  |  | 
  | 
1286  | 0  |     if (val) { | 
1287  | 0  |         flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;  | 
1288  | 0  |     } else { | 
1289  | 0  |         flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT;  | 
1290  | 0  |     }  | 
1291  | 0  |     mod->internal = flags;  | 
1292  | 0  | }  | 
1293  |  |  | 
1294  |  | /*  | 
1295  |  |  * copy desc and value into target. Target is known to be big enough to  | 
1296  |  |  * hold desc +2 +value, which is good because the result of this will be  | 
1297  |  |  * *desc"*value". We may, however, have to add some escapes for special  | 
1298  |  |  * characters imbedded into value (rare). This string potentially comes from  | 
1299  |  |  * a user, so we don't want the user overflowing the target buffer by using  | 
1300  |  |  * excessive escapes. To prevent this we count the escapes we need to add and  | 
1301  |  |  * try to expand the buffer with Realloc.  | 
1302  |  |  */  | 
1303  |  | static char *  | 
1304  |  | secmod_doDescCopy(char *target, char **base, int *baseLen,  | 
1305  |  |                   const char *desc, int descLen, char *value)  | 
1306  | 0  | { | 
1307  | 0  |     int diff, esc_len;  | 
1308  |  | 
  | 
1309  | 0  |     esc_len = NSSUTIL_EscapeSize(value, '\"') - 1;  | 
1310  | 0  |     diff = esc_len - strlen(value);  | 
1311  | 0  |     if (diff > 0) { | 
1312  |  |         /* we need to escape... expand newSpecPtr as well to make sure  | 
1313  |  |          * we don't overflow it */  | 
1314  | 0  |         int offset = target - *base;  | 
1315  | 0  |         char *newPtr = PORT_Realloc(*base, *baseLen + diff);  | 
1316  | 0  |         if (!newPtr) { | 
1317  | 0  |             return target; /* not enough space, just drop the whole copy */  | 
1318  | 0  |         }  | 
1319  | 0  |         *baseLen += diff;  | 
1320  | 0  |         target = newPtr + offset;  | 
1321  | 0  |         *base = newPtr;  | 
1322  | 0  |         value = NSSUTIL_Escape(value, '\"');  | 
1323  | 0  |         if (value == NULL) { | 
1324  | 0  |             return target; /* couldn't escape value, just drop the copy */  | 
1325  | 0  |         }  | 
1326  | 0  |     }  | 
1327  | 0  |     PORT_Memcpy(target, desc, descLen);  | 
1328  | 0  |     target += descLen;  | 
1329  | 0  |     *target++ = '\"';  | 
1330  | 0  |     PORT_Memcpy(target, value, esc_len);  | 
1331  | 0  |     target += esc_len;  | 
1332  | 0  |     *target++ = '\"';  | 
1333  | 0  |     if (diff > 0) { | 
1334  | 0  |         PORT_Free(value);  | 
1335  | 0  |     }  | 
1336  | 0  |     return target;  | 
1337  | 0  | }  | 
1338  |  |  | 
1339  |  | #define SECMOD_SPEC_COPY(new, start, end) \  | 
1340  | 0  |     if (end > start) {                    \ | 
1341  | 0  |         int _cnt = end - start;           \  | 
1342  | 0  |         PORT_Memcpy(new, start, _cnt);    \  | 
1343  | 0  |         new += _cnt;                      \  | 
1344  | 0  |     }  | 
1345  |  | #define SECMOD_TOKEN_DESCRIPTION "tokenDescription="  | 
1346  |  | #define SECMOD_SLOT_DESCRIPTION "slotDescription="  | 
1347  |  |  | 
1348  |  | /*  | 
1349  |  |  * Find any tokens= values in the module spec.  | 
1350  |  |  * Always return a new spec which does not have any tokens= arguments.  | 
1351  |  |  * If tokens= arguments are found, Split the the various tokens defined into  | 
1352  |  |  * an array of child specs to return.  | 
1353  |  |  *  | 
1354  |  |  * Caller is responsible for freeing the child spec and the new token  | 
1355  |  |  * spec.  | 
1356  |  |  */  | 
1357  |  | char *  | 
1358  |  | secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS,  | 
1359  |  |                                 const char *moduleSpec, char ***children,  | 
1360  |  |                                 CK_SLOT_ID **ids)  | 
1361  | 0  | { | 
1362  | 0  |     int newSpecLen = PORT_Strlen(moduleSpec) + 2;  | 
1363  | 0  |     char *newSpec = PORT_Alloc(newSpecLen);  | 
1364  | 0  |     char *newSpecPtr = newSpec;  | 
1365  | 0  |     const char *modulePrev = moduleSpec;  | 
1366  | 0  |     char *target = NULL;  | 
1367  | 0  |     char *tmp = NULL;  | 
1368  | 0  |     char **childArray = NULL;  | 
1369  | 0  |     const char *tokenIndex;  | 
1370  | 0  |     CK_SLOT_ID *idArray = NULL;  | 
1371  | 0  |     int tokenCount = 0;  | 
1372  | 0  |     int i;  | 
1373  |  | 
  | 
1374  | 0  |     if (newSpec == NULL) { | 
1375  | 0  |         return NULL;  | 
1376  | 0  |     }  | 
1377  |  |  | 
1378  | 0  |     *children = NULL;  | 
1379  | 0  |     if (ids) { | 
1380  | 0  |         *ids = NULL;  | 
1381  | 0  |     }  | 
1382  | 0  |     moduleSpec = NSSUTIL_ArgStrip(moduleSpec);  | 
1383  | 0  |     SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);  | 
1384  |  |  | 
1385  |  |     /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening  | 
1386  |  |      * a new softoken module takes the following parameters to name the  | 
1387  |  |      * various tokens:  | 
1388  |  |      *  | 
1389  |  |      *  cryptoTokenDescription: name of the non-fips crypto token.  | 
1390  |  |      *  cryptoSlotDescription: name of the non-fips crypto slot.  | 
1391  |  |      *  dbTokenDescription: name of the non-fips db token.  | 
1392  |  |      *  dbSlotDescription: name of the non-fips db slot.  | 
1393  |  |      *  FIPSTokenDescription: name of the fips db/crypto token.  | 
1394  |  |      *  FIPSSlotDescription: name of the fips db/crypto slot.  | 
1395  |  |      *  | 
1396  |  |      * if we are opening a new slot, we need to have the following  | 
1397  |  |      * parameters:  | 
1398  |  |      *  tokenDescription: name of the token.  | 
1399  |  |      *  slotDescription: name of the slot.  | 
1400  |  |      *  | 
1401  |  |      *  | 
1402  |  |      * The convert flag tells us to drop the unnecessary *TokenDescription  | 
1403  |  |      * and *SlotDescription arguments and convert the appropriate pair  | 
1404  |  |      * (either db or FIPS based on the isFIPS flag) to tokenDescription and  | 
1405  |  |      * slotDescription).  | 
1406  |  |      */  | 
1407  |  |     /*  | 
1408  |  |      * walk down the list. if we find a tokens= argument, save it,  | 
1409  |  |      * otherise copy the argument.  | 
1410  |  |      */  | 
1411  | 0  |     while (*moduleSpec) { | 
1412  | 0  |         int next;  | 
1413  | 0  |         modulePrev = moduleSpec;  | 
1414  | 0  |         NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=",  | 
1415  | 0  |                                   modulePrev = moduleSpec;  | 
1416  | 0  |                                   /* skip copying */)  | 
1417  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1418  | 0  |             moduleSpec, tmp, "cryptoTokenDescription=",  | 
1419  | 0  |             if (convert) { modulePrev = moduleSpec; }) | 
1420  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1421  | 0  |             moduleSpec, tmp, "cryptoSlotDescription=",  | 
1422  | 0  |             if (convert) { modulePrev = moduleSpec; }) | 
1423  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1424  | 0  |             moduleSpec, tmp, "dbTokenDescription=",  | 
1425  | 0  |             if (convert) { | 
1426  | 0  |                 modulePrev = moduleSpec;  | 
1427  | 0  |                 if (!isFIPS) { | 
1428  | 0  |                     newSpecPtr = secmod_doDescCopy(newSpecPtr,  | 
1429  | 0  |                                                    &newSpec, &newSpecLen,  | 
1430  | 0  |                                                    SECMOD_TOKEN_DESCRIPTION,  | 
1431  | 0  |                                                    sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,  | 
1432  | 0  |                                                    tmp);  | 
1433  | 0  |                 }  | 
1434  | 0  |             })  | 
1435  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1436  | 0  |             moduleSpec, tmp, "dbSlotDescription=",  | 
1437  | 0  |             if (convert) { | 
1438  | 0  |                 modulePrev = moduleSpec; /* skip copying */  | 
1439  | 0  |                 if (!isFIPS) { | 
1440  | 0  |                     newSpecPtr = secmod_doDescCopy(newSpecPtr,  | 
1441  | 0  |                                                    &newSpec, &newSpecLen,  | 
1442  | 0  |                                                    SECMOD_SLOT_DESCRIPTION,  | 
1443  | 0  |                                                    sizeof(SECMOD_SLOT_DESCRIPTION) - 1,  | 
1444  | 0  |                                                    tmp);  | 
1445  | 0  |                 }  | 
1446  | 0  |             })  | 
1447  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1448  | 0  |             moduleSpec, tmp, "FIPSTokenDescription=",  | 
1449  | 0  |             if (convert) { | 
1450  | 0  |                 modulePrev = moduleSpec; /* skip copying */  | 
1451  | 0  |                 if (isFIPS) { | 
1452  | 0  |                     newSpecPtr = secmod_doDescCopy(newSpecPtr,  | 
1453  | 0  |                                                    &newSpec, &newSpecLen,  | 
1454  | 0  |                                                    SECMOD_TOKEN_DESCRIPTION,  | 
1455  | 0  |                                                    sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,  | 
1456  | 0  |                                                    tmp);  | 
1457  | 0  |                 }  | 
1458  | 0  |             })  | 
1459  | 0  |         NSSUTIL_HANDLE_STRING_ARG(  | 
1460  | 0  |             moduleSpec, tmp, "FIPSSlotDescription=",  | 
1461  | 0  |             if (convert) { | 
1462  | 0  |                 modulePrev = moduleSpec; /* skip copying */  | 
1463  | 0  |                 if (isFIPS) { | 
1464  | 0  |                     newSpecPtr = secmod_doDescCopy(newSpecPtr,  | 
1465  | 0  |                                                    &newSpec, &newSpecLen,  | 
1466  | 0  |                                                    SECMOD_SLOT_DESCRIPTION,  | 
1467  | 0  |                                                    sizeof(SECMOD_SLOT_DESCRIPTION) - 1,  | 
1468  | 0  |                                                    tmp);  | 
1469  | 0  |                 }  | 
1470  | 0  |             })  | 
1471  | 0  |         NSSUTIL_HANDLE_FINAL_ARG(moduleSpec)  | 
1472  | 0  |         SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);  | 
1473  | 0  |     }  | 
1474  | 0  |     if (tmp) { | 
1475  | 0  |         PORT_Free(tmp);  | 
1476  | 0  |         tmp = NULL;  | 
1477  | 0  |     }  | 
1478  | 0  |     *newSpecPtr = 0;  | 
1479  |  |  | 
1480  |  |     /* no target found, return the newSpec */  | 
1481  | 0  |     if (target == NULL) { | 
1482  | 0  |         return newSpec;  | 
1483  | 0  |     }  | 
1484  |  |  | 
1485  |  |     /* now build the child array from target */  | 
1486  |  |     /*first count them */  | 
1487  | 0  |     for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex;  | 
1488  | 0  |          tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) { | 
1489  | 0  |         tokenCount++;  | 
1490  | 0  |     }  | 
1491  |  | 
  | 
1492  | 0  |     childArray = PORT_NewArray(char *, tokenCount + 1);  | 
1493  | 0  |     if (childArray == NULL) { | 
1494  |  |         /* just return the spec as is then */  | 
1495  | 0  |         PORT_Free(target);  | 
1496  | 0  |         return newSpec;  | 
1497  | 0  |     }  | 
1498  | 0  |     if (ids) { | 
1499  | 0  |         idArray = PORT_NewArray(CK_SLOT_ID, tokenCount + 1);  | 
1500  | 0  |         if (idArray == NULL) { | 
1501  | 0  |             PORT_Free(childArray);  | 
1502  | 0  |             PORT_Free(target);  | 
1503  | 0  |             return newSpec;  | 
1504  | 0  |         }  | 
1505  | 0  |     }  | 
1506  |  |  | 
1507  |  |     /* now fill them in */  | 
1508  | 0  |     for (tokenIndex = NSSUTIL_ArgStrip(target), i = 0;  | 
1509  | 0  |          *tokenIndex && (i < tokenCount);  | 
1510  | 0  |          tokenIndex = NSSUTIL_ArgStrip(tokenIndex)) { | 
1511  | 0  |         int next;  | 
1512  | 0  |         char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next);  | 
1513  | 0  |         tokenIndex += next;  | 
1514  |  | 
  | 
1515  | 0  |         if (idArray) { | 
1516  | 0  |             idArray[i] = NSSUTIL_ArgDecodeNumber(name);  | 
1517  | 0  |         }  | 
1518  |  | 
  | 
1519  | 0  |         PORT_Free(name); /* drop the explicit number */  | 
1520  |  |  | 
1521  |  |         /* if anything is left, copy the args to the child array */  | 
1522  | 0  |         if (!NSSUTIL_ArgIsBlank(*tokenIndex)) { | 
1523  | 0  |             childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next);  | 
1524  | 0  |             tokenIndex += next;  | 
1525  | 0  |         }  | 
1526  | 0  |     }  | 
1527  |  | 
  | 
1528  | 0  |     PORT_Free(target);  | 
1529  | 0  |     childArray[i] = 0;  | 
1530  | 0  |     if (idArray) { | 
1531  | 0  |         idArray[i] = 0;  | 
1532  | 0  |     }  | 
1533  |  |  | 
1534  |  |     /* return it */  | 
1535  | 0  |     *children = childArray;  | 
1536  | 0  |     if (ids) { | 
1537  | 0  |         *ids = idArray;  | 
1538  | 0  |     }  | 
1539  | 0  |     return newSpec;  | 
1540  | 0  | }  | 
1541  |  |  | 
1542  |  | /* get the database and flags from the spec */  | 
1543  |  | static char *  | 
1544  |  | secmod_getConfigDir(const char *spec, char **certPrefix, char **keyPrefix,  | 
1545  |  |                     PRBool *readOnly)  | 
1546  | 0  | { | 
1547  | 0  |     char *config = NULL;  | 
1548  |  | 
  | 
1549  | 0  |     *certPrefix = NULL;  | 
1550  | 0  |     *keyPrefix = NULL;  | 
1551  | 0  |     *readOnly = NSSUTIL_ArgHasFlag("flags", "readOnly", spec); | 
1552  | 0  |     if (NSSUTIL_ArgHasFlag("flags", "nocertdb", spec) || | 
1553  | 0  |         NSSUTIL_ArgHasFlag("flags", "nokeydb", spec)) { | 
1554  | 0  |         return NULL;  | 
1555  | 0  |     }  | 
1556  |  |  | 
1557  | 0  |     spec = NSSUTIL_ArgStrip(spec);  | 
1558  | 0  |     while (*spec) { | 
1559  | 0  |         int next;  | 
1560  | 0  |         NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;)  | 
1561  | 0  |         NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;)  | 
1562  | 0  |         NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;)  | 
1563  | 0  |         NSSUTIL_HANDLE_FINAL_ARG(spec)  | 
1564  | 0  |     }  | 
1565  | 0  |     return config;  | 
1566  | 0  | }  | 
1567  |  |  | 
1568  |  | struct SECMODConfigListStr { | 
1569  |  |     char *config;  | 
1570  |  |     char *certPrefix;  | 
1571  |  |     char *keyPrefix;  | 
1572  |  |     PRBool isReadOnly;  | 
1573  |  | };  | 
1574  |  |  | 
1575  |  | /*  | 
1576  |  |  * return an array of already openned databases from a spec list.  | 
1577  |  |  */  | 
1578  |  | SECMODConfigList *  | 
1579  |  | secmod_GetConfigList(PRBool isFIPS, char *spec, int *count)  | 
1580  | 0  | { | 
1581  | 0  |     char **children;  | 
1582  | 0  |     CK_SLOT_ID *ids;  | 
1583  | 0  |     char *strippedSpec;  | 
1584  | 0  |     int childCount;  | 
1585  | 0  |     SECMODConfigList *conflist = NULL;  | 
1586  | 0  |     int i;  | 
1587  |  | 
  | 
1588  | 0  |     strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS,  | 
1589  | 0  |                                                    spec, &children, &ids);  | 
1590  | 0  |     if (strippedSpec == NULL) { | 
1591  | 0  |         return NULL;  | 
1592  | 0  |     }  | 
1593  |  |  | 
1594  | 0  |     for (childCount = 0; children && children[childCount]; childCount++)  | 
1595  | 0  |         ;  | 
1596  | 0  |     *count = childCount + 1; /* include strippedSpec */  | 
1597  | 0  |     conflist = PORT_NewArray(SECMODConfigList, *count);  | 
1598  | 0  |     if (conflist == NULL) { | 
1599  | 0  |         *count = 0;  | 
1600  | 0  |         goto loser;  | 
1601  | 0  |     }  | 
1602  |  |  | 
1603  | 0  |     conflist[0].config = secmod_getConfigDir(strippedSpec,  | 
1604  | 0  |                                              &conflist[0].certPrefix,  | 
1605  | 0  |                                              &conflist[0].keyPrefix,  | 
1606  | 0  |                                              &conflist[0].isReadOnly);  | 
1607  | 0  |     for (i = 0; i < childCount; i++) { | 
1608  | 0  |         conflist[i + 1].config = secmod_getConfigDir(children[i],  | 
1609  | 0  |                                                      &conflist[i + 1].certPrefix,  | 
1610  | 0  |                                                      &conflist[i + 1].keyPrefix,  | 
1611  | 0  |                                                      &conflist[i + 1].isReadOnly);  | 
1612  | 0  |     }  | 
1613  |  | 
  | 
1614  | 0  | loser:  | 
1615  | 0  |     secmod_FreeChildren(children, ids);  | 
1616  | 0  |     PORT_Free(strippedSpec);  | 
1617  | 0  |     return conflist;  | 
1618  | 0  | }  | 
1619  |  |  | 
1620  |  | /*  | 
1621  |  |  * determine if we are trying to open an old dbm database. For this test  | 
1622  |  |  * RDB databases should return PR_FALSE.  | 
1623  |  |  */  | 
1624  |  | static PRBool  | 
1625  |  | secmod_configIsDBM(char *configDir)  | 
1626  | 0  | { | 
1627  | 0  |     char *env;  | 
1628  |  |  | 
1629  |  |     /* explicit dbm open */  | 
1630  | 0  |     if (strncmp(configDir, "dbm:", 4) == 0) { | 
1631  | 0  |         return PR_TRUE;  | 
1632  | 0  |     }  | 
1633  |  |     /* explicit open of a non-dbm database */  | 
1634  | 0  |     if ((strncmp(configDir, "sql:", 4) == 0) ||  | 
1635  | 0  |         (strncmp(configDir, "rdb:", 4) == 0) ||  | 
1636  | 0  |         (strncmp(configDir, "extern:", 7) == 0)) { | 
1637  | 0  |         return PR_FALSE;  | 
1638  | 0  |     }  | 
1639  | 0  |     env = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE"); | 
1640  |  |     /* implicit dbm open */  | 
1641  | 0  |     if ((env == NULL) || (strcmp(env, "dbm") == 0)) { | 
1642  | 0  |         return PR_TRUE;  | 
1643  | 0  |     }  | 
1644  |  |     /* implicit non-dbm open */  | 
1645  | 0  |     return PR_FALSE;  | 
1646  | 0  | }  | 
1647  |  |  | 
1648  |  | /*  | 
1649  |  |  * match two prefixes. prefix may be NULL. NULL patches '\0'  | 
1650  |  |  */  | 
1651  |  | static PRBool  | 
1652  |  | secmod_matchPrefix(char *prefix1, char *prefix2)  | 
1653  | 0  | { | 
1654  | 0  |     if ((prefix1 == NULL) || (*prefix1 == 0)) { | 
1655  | 0  |         if ((prefix2 == NULL) || (*prefix2 == 0)) { | 
1656  | 0  |             return PR_TRUE;  | 
1657  | 0  |         }  | 
1658  | 0  |         return PR_FALSE;  | 
1659  | 0  |     }  | 
1660  | 0  |     if (strcmp(prefix1, prefix2) == 0) { | 
1661  | 0  |         return PR_TRUE;  | 
1662  | 0  |     }  | 
1663  | 0  |     return PR_FALSE;  | 
1664  | 0  | }  | 
1665  |  |  | 
1666  |  | /* do two config paramters match? Not all callers are compariing  | 
1667  |  |  * SECMODConfigLists directly, so this function breaks them out to their  | 
1668  |  |  * components. */  | 
1669  |  | static PRBool  | 
1670  |  | secmod_matchConfig(char *configDir1, char *configDir2,  | 
1671  |  |                    char *certPrefix1, char *certPrefix2,  | 
1672  |  |                    char *keyPrefix1, char *keyPrefix2,  | 
1673  |  |                    PRBool isReadOnly1, PRBool isReadOnly2)  | 
1674  | 0  | { | 
1675  |  |     /* TODO: Document the answer to the question:  | 
1676  |  |      *       "Why not allow them to match if they are both NULL?"  | 
1677  |  |      * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1318633#c1  | 
1678  |  |      */  | 
1679  | 0  |     if ((configDir1 == NULL) || (configDir2 == NULL)) { | 
1680  | 0  |         return PR_FALSE;  | 
1681  | 0  |     }  | 
1682  | 0  |     if (strcmp(configDir1, configDir2) != 0) { | 
1683  | 0  |         return PR_FALSE;  | 
1684  | 0  |     }  | 
1685  | 0  |     if (!secmod_matchPrefix(certPrefix1, certPrefix2)) { | 
1686  | 0  |         return PR_FALSE;  | 
1687  | 0  |     }  | 
1688  | 0  |     if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) { | 
1689  | 0  |         return PR_FALSE;  | 
1690  | 0  |     }  | 
1691  |  |     /* these last test -- if we just need the DB open read only,  | 
1692  |  |      * than any open will suffice, but if we requested it read/write  | 
1693  |  |      * and it's only open read only, we need to open it again */  | 
1694  | 0  |     if (isReadOnly1) { | 
1695  | 0  |         return PR_TRUE;  | 
1696  | 0  |     }  | 
1697  | 0  |     if (isReadOnly2) { /* isReadonly1 == PR_FALSE */ | 
1698  | 0  |         return PR_FALSE;  | 
1699  | 0  |     }  | 
1700  | 0  |     return PR_TRUE;  | 
1701  | 0  | }  | 
1702  |  |  | 
1703  |  | /*  | 
1704  |  |  * return true if we are requesting a database that is already openned.  | 
1705  |  |  */  | 
1706  |  | PRBool  | 
1707  |  | secmod_MatchConfigList(const char *spec, SECMODConfigList *conflist, int count)  | 
1708  | 0  | { | 
1709  | 0  |     char *config;  | 
1710  | 0  |     char *certPrefix;  | 
1711  | 0  |     char *keyPrefix;  | 
1712  | 0  |     PRBool isReadOnly;  | 
1713  | 0  |     PRBool ret = PR_FALSE;  | 
1714  | 0  |     int i;  | 
1715  |  | 
  | 
1716  | 0  |     config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly);  | 
1717  | 0  |     if (!config) { | 
1718  | 0  |         goto done;  | 
1719  | 0  |     }  | 
1720  |  |  | 
1721  |  |     /* NOTE: we dbm isn't multiple open safe. If we open the same database  | 
1722  |  |      * twice from two different locations, then we can corrupt our database  | 
1723  |  |      * (the cache will be inconsistent). Protect against this by claiming  | 
1724  |  |      * for comparison only that we are always openning dbm databases read only.  | 
1725  |  |      */  | 
1726  | 0  |     if (secmod_configIsDBM(config)) { | 
1727  | 0  |         isReadOnly = 1;  | 
1728  | 0  |     }  | 
1729  | 0  |     for (i = 0; i < count; i++) { | 
1730  | 0  |         if (secmod_matchConfig(config, conflist[i].config, certPrefix,  | 
1731  | 0  |                                conflist[i].certPrefix, keyPrefix,  | 
1732  | 0  |                                conflist[i].keyPrefix, isReadOnly,  | 
1733  | 0  |                                conflist[i].isReadOnly)) { | 
1734  | 0  |             ret = PR_TRUE;  | 
1735  | 0  |             goto done;  | 
1736  | 0  |         }  | 
1737  | 0  |     }  | 
1738  |  |  | 
1739  | 0  |     ret = PR_FALSE;  | 
1740  | 0  | done:  | 
1741  | 0  |     PORT_Free(config);  | 
1742  | 0  |     PORT_Free(certPrefix);  | 
1743  | 0  |     PORT_Free(keyPrefix);  | 
1744  | 0  |     return ret;  | 
1745  | 0  | }  | 
1746  |  |  | 
1747  |  | /*  | 
1748  |  |  * Find the slot id from the module spec. If the slot is the database slot, we  | 
1749  |  |  * can get the slot id from the default database slot.  | 
1750  |  |  */  | 
1751  |  | CK_SLOT_ID  | 
1752  |  | secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module)  | 
1753  | 0  | { | 
1754  | 0  |     char *tmp_spec = NULL;  | 
1755  | 0  |     char **children, **thisChild;  | 
1756  | 0  |     CK_SLOT_ID *ids, *thisID, slotID = -1;  | 
1757  | 0  |     char *inConfig = NULL, *thisConfig = NULL;  | 
1758  | 0  |     char *inCertPrefix = NULL, *thisCertPrefix = NULL;  | 
1759  | 0  |     char *inKeyPrefix = NULL, *thisKeyPrefix = NULL;  | 
1760  | 0  |     PRBool inReadOnly, thisReadOnly;  | 
1761  |  | 
  | 
1762  | 0  |     inConfig = secmod_getConfigDir(moduleSpec, &inCertPrefix, &inKeyPrefix,  | 
1763  | 0  |                                    &inReadOnly);  | 
1764  | 0  |     if (!inConfig) { | 
1765  | 0  |         goto done;  | 
1766  | 0  |     }  | 
1767  |  |  | 
1768  | 0  |     if (secmod_configIsDBM(inConfig)) { | 
1769  | 0  |         inReadOnly = 1;  | 
1770  | 0  |     }  | 
1771  |  | 
  | 
1772  | 0  |     tmp_spec = secmod_ParseModuleSpecForTokens(PR_TRUE, module->isFIPS,  | 
1773  | 0  |                                                module->libraryParams, &children, &ids);  | 
1774  | 0  |     if (tmp_spec == NULL) { | 
1775  | 0  |         goto done;  | 
1776  | 0  |     }  | 
1777  |  |  | 
1778  |  |     /* first check to see if the parent is the database */  | 
1779  | 0  |     thisConfig = secmod_getConfigDir(tmp_spec, &thisCertPrefix, &thisKeyPrefix,  | 
1780  | 0  |                                      &thisReadOnly);  | 
1781  | 0  |     if (!thisConfig) { | 
1782  | 0  |         goto done;  | 
1783  | 0  |     }  | 
1784  | 0  |     if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,  | 
1785  | 0  |                            inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) { | 
1786  |  |         /* yup it's the default key slot, get the id for it */  | 
1787  | 0  |         PK11SlotInfo *slot = PK11_GetInternalKeySlot();  | 
1788  | 0  |         if (slot) { | 
1789  | 0  |             slotID = slot->slotID;  | 
1790  | 0  |             PK11_FreeSlot(slot);  | 
1791  | 0  |         }  | 
1792  | 0  |         goto done;  | 
1793  | 0  |     }  | 
1794  |  |  | 
1795  |  |     /* find id of the token */  | 
1796  | 0  |     for (thisChild = children, thisID = ids; thisChild && *thisChild; thisChild++, thisID++) { | 
1797  | 0  |         PORT_Free(thisConfig);  | 
1798  | 0  |         PORT_Free(thisCertPrefix);  | 
1799  | 0  |         PORT_Free(thisKeyPrefix);  | 
1800  | 0  |         thisConfig = secmod_getConfigDir(*thisChild, &thisCertPrefix,  | 
1801  | 0  |                                          &thisKeyPrefix, &thisReadOnly);  | 
1802  | 0  |         if (thisConfig == NULL) { | 
1803  | 0  |             continue;  | 
1804  | 0  |         }  | 
1805  | 0  |         if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,  | 
1806  | 0  |                                inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) { | 
1807  | 0  |             slotID = *thisID;  | 
1808  | 0  |             break;  | 
1809  | 0  |         }  | 
1810  | 0  |     }  | 
1811  |  | 
  | 
1812  | 0  | done:  | 
1813  | 0  |     PORT_Free(inConfig);  | 
1814  | 0  |     PORT_Free(inCertPrefix);  | 
1815  | 0  |     PORT_Free(inKeyPrefix);  | 
1816  | 0  |     PORT_Free(thisConfig);  | 
1817  | 0  |     PORT_Free(thisCertPrefix);  | 
1818  | 0  |     PORT_Free(thisKeyPrefix);  | 
1819  | 0  |     if (tmp_spec) { | 
1820  | 0  |         secmod_FreeChildren(children, ids);  | 
1821  | 0  |         PORT_Free(tmp_spec);  | 
1822  | 0  |     }  | 
1823  | 0  |     return slotID;  | 
1824  | 0  | }  | 
1825  |  |  | 
1826  |  | void  | 
1827  |  | secmod_FreeConfigList(SECMODConfigList *conflist, int count)  | 
1828  | 0  | { | 
1829  | 0  |     int i;  | 
1830  | 0  |     for (i = 0; i < count; i++) { | 
1831  | 0  |         PORT_Free(conflist[i].config);  | 
1832  | 0  |         PORT_Free(conflist[i].certPrefix);  | 
1833  | 0  |         PORT_Free(conflist[i].keyPrefix);  | 
1834  | 0  |     }  | 
1835  | 0  |     PORT_Free(conflist);  | 
1836  | 0  | }  | 
1837  |  |  | 
1838  |  | void  | 
1839  |  | secmod_FreeChildren(char **children, CK_SLOT_ID *ids)  | 
1840  | 0  | { | 
1841  | 0  |     char **thisChild;  | 
1842  |  | 
  | 
1843  | 0  |     if (!children) { | 
1844  | 0  |         return;  | 
1845  | 0  |     }  | 
1846  |  |  | 
1847  | 0  |     for (thisChild = children; thisChild && *thisChild; thisChild++) { | 
1848  | 0  |         PORT_Free(*thisChild);  | 
1849  | 0  |     }  | 
1850  | 0  |     PORT_Free(children);  | 
1851  | 0  |     if (ids) { | 
1852  | 0  |         PORT_Free(ids);  | 
1853  | 0  |     }  | 
1854  | 0  |     return;  | 
1855  | 0  | }  | 
1856  |  |  | 
1857  |  | /*  | 
1858  |  |  * caclulate the length of each child record:  | 
1859  |  |  * " 0x{id}=<{escaped_child}>" | 
1860  |  |  */  | 
1861  |  | static int  | 
1862  |  | secmod_getChildLength(char *child, CK_SLOT_ID id)  | 
1863  | 0  | { | 
1864  | 0  |     int length = NSSUTIL_DoubleEscapeSize(child, '>', ']');  | 
1865  | 0  |     if (id == 0) { | 
1866  | 0  |         length++;  | 
1867  | 0  |     }  | 
1868  | 0  |     while (id) { | 
1869  | 0  |         length++;  | 
1870  | 0  |         id = id >> 4;  | 
1871  | 0  |     }  | 
1872  | 0  |     length += 6; /* {sp}0x[id]=<{child}> */ | 
1873  | 0  |     return length;  | 
1874  | 0  | }  | 
1875  |  |  | 
1876  |  | /*  | 
1877  |  |  * Build a child record:  | 
1878  |  |  * " 0x{id}=<{escaped_child}>" | 
1879  |  |  */  | 
1880  |  | static SECStatus  | 
1881  |  | secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id)  | 
1882  | 0  | { | 
1883  | 0  |     int len;  | 
1884  | 0  |     char *escSpec;  | 
1885  |  | 
  | 
1886  | 0  |     len = PR_snprintf(*next, *length, " 0x%x=<", id);  | 
1887  | 0  |     if (len < 0) { | 
1888  | 0  |         return SECFailure;  | 
1889  | 0  |     }  | 
1890  | 0  |     *next += len;  | 
1891  | 0  |     *length -= len;  | 
1892  | 0  |     escSpec = NSSUTIL_DoubleEscape(child, '>', ']');  | 
1893  | 0  |     if (escSpec == NULL) { | 
1894  | 0  |         return SECFailure;  | 
1895  | 0  |     }  | 
1896  | 0  |     if (*child && (*escSpec == 0)) { | 
1897  | 0  |         PORT_Free(escSpec);  | 
1898  | 0  |         return SECFailure;  | 
1899  | 0  |     }  | 
1900  | 0  |     len = strlen(escSpec);  | 
1901  | 0  |     if (len + 1 > *length) { | 
1902  | 0  |         PORT_Free(escSpec);  | 
1903  | 0  |         return SECFailure;  | 
1904  | 0  |     }  | 
1905  | 0  |     PORT_Memcpy(*next, escSpec, len);  | 
1906  | 0  |     *next += len;  | 
1907  | 0  |     *length -= len;  | 
1908  | 0  |     PORT_Free(escSpec);  | 
1909  | 0  |     **next = '>';  | 
1910  | 0  |     (*next)++;  | 
1911  | 0  |     (*length)--;  | 
1912  | 0  |     return SECSuccess;  | 
1913  | 0  | }  | 
1914  |  |  | 
1915  | 0  | #define TOKEN_STRING " tokens=["  | 
1916  |  |  | 
1917  |  | char *  | 
1918  |  | secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken,  | 
1919  |  |                           CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids)  | 
1920  | 0  | { | 
1921  | 0  |     char *rawParam = NULL;  /* oldParam with tokens stripped off */  | 
1922  | 0  |     char *newParam = NULL;  /* space for the return parameter */  | 
1923  | 0  |     char *nextParam = NULL; /* current end of the new parameter */  | 
1924  | 0  |     char **oldChildren = NULL;  | 
1925  | 0  |     CK_SLOT_ID *oldIds = NULL;  | 
1926  | 0  |     void *mark = NULL; /* mark the arena pool in case we need  | 
1927  |  |                         * to release it */  | 
1928  | 0  |     int length, i, tmpLen;  | 
1929  | 0  |     SECStatus rv;  | 
1930  |  |  | 
1931  |  |     /* first strip out and save the old tokenlist */  | 
1932  | 0  |     rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE, PR_FALSE,  | 
1933  | 0  |                                                oldParam, &oldChildren, &oldIds);  | 
1934  | 0  |     if (!rawParam) { | 
1935  | 0  |         goto loser;  | 
1936  | 0  |     }  | 
1937  |  |  | 
1938  |  |     /* now calculate the total length of the new buffer */  | 
1939  |  |     /* First the 'fixed stuff', length of rawparam (does not include a NULL),  | 
1940  |  |      * length of the token string (does include the NULL), closing bracket */  | 
1941  | 0  |     length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1;  | 
1942  |  |     /* now add then length of all the old children */  | 
1943  | 0  |     for (i = 0; oldChildren && oldChildren[i]; i++) { | 
1944  | 0  |         length += secmod_getChildLength(oldChildren[i], oldIds[i]);  | 
1945  | 0  |     }  | 
1946  |  |  | 
1947  |  |     /* add the new token */  | 
1948  | 0  |     length += secmod_getChildLength(newToken, newID);  | 
1949  |  |  | 
1950  |  |     /* and it's new children */  | 
1951  | 0  |     for (i = 0; children && children[i]; i++) { | 
1952  | 0  |         if (ids[i] == -1) { | 
1953  | 0  |             continue;  | 
1954  | 0  |         }  | 
1955  | 0  |         length += secmod_getChildLength(children[i], ids[i]);  | 
1956  | 0  |     }  | 
1957  |  |  | 
1958  |  |     /* now allocate and build the string */  | 
1959  | 0  |     mark = PORT_ArenaMark(arena);  | 
1960  | 0  |     if (!mark) { | 
1961  | 0  |         goto loser;  | 
1962  | 0  |     }  | 
1963  | 0  |     newParam = PORT_ArenaAlloc(arena, length);  | 
1964  | 0  |     if (!newParam) { | 
1965  | 0  |         goto loser;  | 
1966  | 0  |     }  | 
1967  |  |  | 
1968  | 0  |     PORT_Strcpy(newParam, oldParam);  | 
1969  | 0  |     tmpLen = strlen(oldParam);  | 
1970  | 0  |     nextParam = newParam + tmpLen;  | 
1971  | 0  |     length -= tmpLen;  | 
1972  | 0  |     PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING) - 1);  | 
1973  | 0  |     nextParam += sizeof(TOKEN_STRING) - 1;  | 
1974  | 0  |     length -= sizeof(TOKEN_STRING) - 1;  | 
1975  |  | 
  | 
1976  | 0  |     for (i = 0; oldChildren && oldChildren[i]; i++) { | 
1977  | 0  |         rv = secmod_mkTokenChild(&nextParam, &length, oldChildren[i], oldIds[i]);  | 
1978  | 0  |         if (rv != SECSuccess) { | 
1979  | 0  |             goto loser;  | 
1980  | 0  |         }  | 
1981  | 0  |     }  | 
1982  |  |  | 
1983  | 0  |     rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID);  | 
1984  | 0  |     if (rv != SECSuccess) { | 
1985  | 0  |         goto loser;  | 
1986  | 0  |     }  | 
1987  |  |  | 
1988  | 0  |     for (i = 0; children && children[i]; i++) { | 
1989  | 0  |         if (ids[i] == -1) { | 
1990  | 0  |             continue;  | 
1991  | 0  |         }  | 
1992  | 0  |         rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]);  | 
1993  | 0  |         if (rv != SECSuccess) { | 
1994  | 0  |             goto loser;  | 
1995  | 0  |         }  | 
1996  | 0  |     }  | 
1997  |  |  | 
1998  | 0  |     if (length < 2) { | 
1999  | 0  |         goto loser;  | 
2000  | 0  |     }  | 
2001  |  |  | 
2002  | 0  |     *nextParam++ = ']';  | 
2003  | 0  |     *nextParam++ = 0;  | 
2004  |  |  | 
2005  |  |     /* we are going to return newParam now, don't release the mark */  | 
2006  | 0  |     PORT_ArenaUnmark(arena, mark);  | 
2007  | 0  |     mark = NULL;  | 
2008  |  | 
  | 
2009  | 0  | loser:  | 
2010  | 0  |     if (mark) { | 
2011  | 0  |         PORT_ArenaRelease(arena, mark);  | 
2012  | 0  |         newParam = NULL; /* if the mark is still active,  | 
2013  |  |                           * don't return the param */  | 
2014  | 0  |     }  | 
2015  | 0  |     if (rawParam) { | 
2016  | 0  |         PORT_Free(rawParam);  | 
2017  | 0  |     }  | 
2018  | 0  |     if (oldChildren) { | 
2019  | 0  |         secmod_FreeChildren(oldChildren, oldIds);  | 
2020  | 0  |     }  | 
2021  | 0  |     return newParam;  | 
2022  | 0  | }  | 
2023  |  |  | 
2024  |  | static char *  | 
2025  |  | secmod_mkModuleSpec(SECMODModule *module)  | 
2026  | 0  | { | 
2027  | 0  |     char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;  | 
2028  | 0  |     int slotCount, i, si;  | 
2029  | 0  |     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();  | 
2030  |  |  | 
2031  |  |     /* allocate target slot info strings */  | 
2032  | 0  |     slotCount = 0;  | 
2033  |  | 
  | 
2034  | 0  |     SECMOD_GetReadLock(moduleLock);  | 
2035  | 0  |     if (module->slotCount) { | 
2036  | 0  |         for (i = 0; i < module->slotCount; i++) { | 
2037  | 0  |             if (module->slots[i]->defaultFlags != 0) { | 
2038  | 0  |                 slotCount++;  | 
2039  | 0  |             }  | 
2040  | 0  |         }  | 
2041  | 0  |     } else { | 
2042  | 0  |         slotCount = module->slotInfoCount;  | 
2043  | 0  |     }  | 
2044  |  | 
  | 
2045  | 0  |     slotStrings = (char **)PORT_ZAlloc(slotCount * sizeof(char *));  | 
2046  | 0  |     if (slotStrings == NULL) { | 
2047  | 0  |         SECMOD_ReleaseReadLock(moduleLock);  | 
2048  | 0  |         goto loser;  | 
2049  | 0  |     }  | 
2050  |  |  | 
2051  |  |     /* build the slot info strings */  | 
2052  | 0  |     if (module->slotCount) { | 
2053  | 0  |         for (i = 0, si = 0; i < module->slotCount; i++) { | 
2054  | 0  |             if (module->slots[i]->defaultFlags) { | 
2055  | 0  |                 PORT_Assert(si < slotCount);  | 
2056  | 0  |                 if (si >= slotCount)  | 
2057  | 0  |                     break;  | 
2058  | 0  |                 slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID,  | 
2059  | 0  |                                                        module->slots[i]->defaultFlags,  | 
2060  | 0  |                                                        module->slots[i]->timeout,  | 
2061  | 0  |                                                        module->slots[i]->askpw,  | 
2062  | 0  |                                                        module->slots[i]->hasRootCerts,  | 
2063  | 0  |                                                        module->slots[i]->hasRootTrust);  | 
2064  | 0  |                 si++;  | 
2065  | 0  |             }  | 
2066  | 0  |         }  | 
2067  | 0  |     } else { | 
2068  | 0  |         for (i = 0; i < slotCount; i++) { | 
2069  | 0  |             slotStrings[i] = NSSUTIL_MkSlotString(  | 
2070  | 0  |                 module->slotInfo[i].slotID,  | 
2071  | 0  |                 module->slotInfo[i].defaultFlags,  | 
2072  | 0  |                 module->slotInfo[i].timeout,  | 
2073  | 0  |                 module->slotInfo[i].askpw,  | 
2074  | 0  |                 module->slotInfo[i].hasRootCerts,  | 
2075  | 0  |                 module->slotInfo[i].hasRootTrust);  | 
2076  | 0  |         }  | 
2077  | 0  |     }  | 
2078  |  | 
  | 
2079  | 0  |     SECMOD_ReleaseReadLock(moduleLock);  | 
2080  | 0  |     nss = NSSUTIL_MkNSSString(slotStrings, slotCount, module->internal,  | 
2081  | 0  |                               module->isFIPS, module->isModuleDB,  | 
2082  | 0  |                               module->moduleDBOnly, module->isCritical,  | 
2083  | 0  |                               module->trustOrder, module->cipherOrder,  | 
2084  | 0  |                               module->ssl[0], module->ssl[1]);  | 
2085  | 0  |     modSpec = NSSUTIL_MkModuleSpec(module->dllName, module->commonName,  | 
2086  | 0  |                                    module->libraryParams, nss);  | 
2087  | 0  |     PORT_Free(slotStrings);  | 
2088  | 0  |     PR_smprintf_free(nss);  | 
2089  | 0  | loser:  | 
2090  | 0  |     return (modSpec);  | 
2091  | 0  | }  | 
2092  |  |  | 
2093  |  | char **  | 
2094  |  | SECMOD_GetModuleSpecList(SECMODModule *module)  | 
2095  | 1  | { | 
2096  | 1  |     SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;  | 
2097  | 1  |     if (func) { | 
2098  | 1  |         return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,  | 
2099  | 1  |                        module->libraryParams, NULL);  | 
2100  | 1  |     }  | 
2101  | 0  |     return NULL;  | 
2102  | 1  | }  | 
2103  |  |  | 
2104  |  | SECStatus  | 
2105  |  | SECMOD_AddPermDB(SECMODModule *module)  | 
2106  | 0  | { | 
2107  | 0  |     SECMODModuleDBFunc func;  | 
2108  | 0  |     char *moduleSpec;  | 
2109  | 0  |     char **retString;  | 
2110  |  | 
  | 
2111  | 0  |     if (module->parent == NULL)  | 
2112  | 0  |         return SECFailure;  | 
2113  |  |  | 
2114  | 0  |     func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;  | 
2115  | 0  |     if (func) { | 
2116  | 0  |         moduleSpec = secmod_mkModuleSpec(module);  | 
2117  | 0  |         retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD,  | 
2118  | 0  |                             module->parent->libraryParams, moduleSpec);  | 
2119  | 0  |         PORT_Free(moduleSpec);  | 
2120  | 0  |         if (retString != NULL)  | 
2121  | 0  |             return SECSuccess;  | 
2122  | 0  |     }  | 
2123  | 0  |     return SECFailure;  | 
2124  | 0  | }  | 
2125  |  |  | 
2126  |  | SECStatus  | 
2127  |  | SECMOD_DeletePermDB(SECMODModule *module)  | 
2128  | 0  | { | 
2129  | 0  |     SECMODModuleDBFunc func;  | 
2130  | 0  |     char *moduleSpec;  | 
2131  | 0  |     char **retString;  | 
2132  |  | 
  | 
2133  | 0  |     if (module->parent == NULL)  | 
2134  | 0  |         return SECFailure;  | 
2135  |  |  | 
2136  | 0  |     func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;  | 
2137  | 0  |     if (func) { | 
2138  | 0  |         moduleSpec = secmod_mkModuleSpec(module);  | 
2139  | 0  |         retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL,  | 
2140  | 0  |                             module->parent->libraryParams, moduleSpec);  | 
2141  | 0  |         PORT_Free(moduleSpec);  | 
2142  | 0  |         if (retString != NULL)  | 
2143  | 0  |             return SECSuccess;  | 
2144  | 0  |     }  | 
2145  | 0  |     return SECFailure;  | 
2146  | 0  | }  | 
2147  |  |  | 
2148  |  | SECStatus  | 
2149  |  | SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList)  | 
2150  | 1  | { | 
2151  | 1  |     SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;  | 
2152  | 1  |     char **retString;  | 
2153  | 1  |     if (func) { | 
2154  | 1  |         retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE,  | 
2155  | 1  |                             module->libraryParams, moduleSpecList);  | 
2156  | 1  |         if (retString != NULL)  | 
2157  | 1  |             return SECSuccess;  | 
2158  | 1  |     }  | 
2159  | 0  |     return SECFailure;  | 
2160  | 1  | }  | 
2161  |  |  | 
2162  |  | /*  | 
2163  |  |  * load a PKCS#11 module but do not add it to the default NSS trust domain  | 
2164  |  |  */  | 
2165  |  | SECMODModule *  | 
2166  |  | SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)  | 
2167  | 2  | { | 
2168  | 2  |     char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss = NULL;  | 
2169  | 2  |     char *config = NULL;  | 
2170  | 2  |     SECStatus status;  | 
2171  | 2  |     SECMODModule *module = NULL;  | 
2172  | 2  |     SECMODModule *oldModule = NULL;  | 
2173  | 2  |     SECStatus rv;  | 
2174  | 2  |     PRBool forwardPolicyFeedback = PR_FALSE;  | 
2175  | 2  |     PRUint32 forwardPolicyCheckFlags;  | 
2176  |  |  | 
2177  |  |     /* initialize the underlying module structures */  | 
2178  | 2  |     SECMOD_Init();  | 
2179  |  |  | 
2180  | 2  |     status = NSSUTIL_ArgParseModuleSpecEx(modulespec, &library, &moduleName,  | 
2181  | 2  |                                           ¶meters, &nss,  | 
2182  | 2  |                                           &config);  | 
2183  | 2  |     if (status != SECSuccess) { | 
2184  | 0  |         goto loser;  | 
2185  | 0  |     }  | 
2186  |  |  | 
2187  | 2  |     module = SECMOD_CreateModuleEx(library, moduleName, parameters, nss, config);  | 
2188  | 2  |     forwardPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss); | 
2189  | 2  |     forwardPolicyCheckFlags = secmod_parsePolicyCheckFlags(nss);  | 
2190  |  |  | 
2191  | 2  |     if (library)  | 
2192  | 0  |         PORT_Free(library);  | 
2193  | 2  |     if (moduleName)  | 
2194  | 2  |         PORT_Free(moduleName);  | 
2195  | 2  |     if (parameters)  | 
2196  | 2  |         PORT_Free(parameters);  | 
2197  | 2  |     if (nss)  | 
2198  | 2  |         PORT_Free(nss);  | 
2199  | 2  |     if (config)  | 
2200  | 0  |         PORT_Free(config);  | 
2201  | 2  |     if (!module) { | 
2202  | 0  |         goto loser;  | 
2203  | 0  |     }  | 
2204  |  |  | 
2205  |  |     /* a policy only stanza doesn't actually get 'loaded'. policy has already  | 
2206  |  |      * been parsed as a side effect of the CreateModuleEx call */  | 
2207  | 2  |     if (secmod_PolicyOnly(module)) { | 
2208  | 0  |         return module;  | 
2209  | 0  |     }  | 
2210  | 2  |     if (parent) { | 
2211  | 1  |         module->parent = SECMOD_ReferenceModule(parent);  | 
2212  | 1  |         if (module->internal && secmod_IsInternalKeySlot(parent)) { | 
2213  | 1  |             module->internal = parent->internal;  | 
2214  | 1  |         }  | 
2215  | 1  |     }  | 
2216  |  |  | 
2217  |  |     /* load it */  | 
2218  | 2  |     rv = secmod_LoadPKCS11Module(module, &oldModule);  | 
2219  | 2  |     if (rv != SECSuccess) { | 
2220  | 0  |         goto loser;  | 
2221  | 0  |     }  | 
2222  |  |  | 
2223  |  |     /* if we just reload an old module, no need to add it to any lists.  | 
2224  |  |      * we simple release all our references */  | 
2225  | 2  |     if (oldModule) { | 
2226  |  |         /* This module already exists, don't link it anywhere. This  | 
2227  |  |          * will probably destroy this module */  | 
2228  | 0  |         SECMOD_DestroyModule(module);  | 
2229  | 0  |         return oldModule;  | 
2230  | 0  |     }  | 
2231  |  |  | 
2232  | 2  |     if (recurse && module->isModuleDB) { | 
2233  | 1  |         char **moduleSpecList;  | 
2234  | 1  |         PORT_SetError(0);  | 
2235  |  |  | 
2236  | 1  |         moduleSpecList = SECMOD_GetModuleSpecList(module);  | 
2237  | 1  |         if (moduleSpecList) { | 
2238  | 1  |             char **index;  | 
2239  |  |  | 
2240  | 1  |             index = moduleSpecList;  | 
2241  | 1  |             if (*index && SECMOD_GetSkipFirstFlag(module)) { | 
2242  | 0  |                 index++;  | 
2243  | 0  |             }  | 
2244  |  |  | 
2245  | 2  |             for (; *index; index++) { | 
2246  | 1  |                 SECMODModule *child;  | 
2247  | 1  |                 if (0 == PORT_Strcmp(*index, modulespec)) { | 
2248  |  |                     /* avoid trivial infinite recursion */  | 
2249  | 0  |                     PORT_SetError(SEC_ERROR_NO_MODULE);  | 
2250  | 0  |                     rv = SECFailure;  | 
2251  | 0  |                     break;  | 
2252  | 0  |                 }  | 
2253  | 1  |                 if (!forwardPolicyFeedback) { | 
2254  | 1  |                     child = SECMOD_LoadModule(*index, module, PR_TRUE);  | 
2255  | 1  |                 } else { | 
2256  |  |                     /* Add printPolicyFeedback to the nss flags */  | 
2257  | 0  |                     char *specWithForwards =  | 
2258  | 0  |                         NSSUTIL_AddNSSFlagToModuleSpec(*index, "printPolicyFeedback");  | 
2259  | 0  |                     char *tmp;  | 
2260  | 0  |                     if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) { | 
2261  | 0  |                         tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckIdentifier");  | 
2262  | 0  |                         PORT_Free(specWithForwards);  | 
2263  | 0  |                         specWithForwards = tmp;  | 
2264  | 0  |                     }  | 
2265  | 0  |                     if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) { | 
2266  | 0  |                         tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckValue");  | 
2267  | 0  |                         PORT_Free(specWithForwards);  | 
2268  | 0  |                         specWithForwards = tmp;  | 
2269  | 0  |                     }  | 
2270  | 0  |                     child = SECMOD_LoadModule(specWithForwards, module, PR_TRUE);  | 
2271  | 0  |                     PORT_Free(specWithForwards);  | 
2272  | 0  |                 }  | 
2273  | 1  |                 if (!child)  | 
2274  | 0  |                     break;  | 
2275  | 1  |                 if (child->isCritical && !child->loaded) { | 
2276  | 0  |                     int err = PORT_GetError();  | 
2277  | 0  |                     if (!err)  | 
2278  | 0  |                         err = SEC_ERROR_NO_MODULE;  | 
2279  | 0  |                     SECMOD_DestroyModule(child);  | 
2280  | 0  |                     PORT_SetError(err);  | 
2281  | 0  |                     rv = SECFailure;  | 
2282  | 0  |                     break;  | 
2283  | 0  |                 }  | 
2284  | 1  |                 SECMOD_DestroyModule(child);  | 
2285  | 1  |             }  | 
2286  | 1  |             SECMOD_FreeModuleSpecList(module, moduleSpecList);  | 
2287  | 1  |         } else { | 
2288  | 0  |             if (!PORT_GetError())  | 
2289  | 0  |                 PORT_SetError(SEC_ERROR_NO_MODULE);  | 
2290  | 0  |             rv = SECFailure;  | 
2291  | 0  |         }  | 
2292  | 1  |     }  | 
2293  |  |  | 
2294  | 2  |     if (rv != SECSuccess) { | 
2295  | 0  |         goto loser;  | 
2296  | 0  |     }  | 
2297  |  |  | 
2298  |  |     /* inherit the reference */  | 
2299  | 2  |     if (!module->moduleDBOnly) { | 
2300  | 1  |         SECMOD_AddModuleToList(module);  | 
2301  | 1  |     } else { | 
2302  | 1  |         SECMOD_AddModuleToDBOnlyList(module);  | 
2303  | 1  |     }  | 
2304  |  |  | 
2305  |  |     /* handle any additional work here */  | 
2306  | 2  |     return module;  | 
2307  |  |  | 
2308  | 0  | loser:  | 
2309  | 0  |     if (module) { | 
2310  | 0  |         if (module->loaded) { | 
2311  | 0  |             SECMOD_UnloadModule(module);  | 
2312  | 0  |         }  | 
2313  | 0  |         SECMOD_AddModuleToUnloadList(module);  | 
2314  | 0  |     }  | 
2315  | 0  |     return module;  | 
2316  | 2  | }  | 
2317  |  |  | 
2318  |  | SECMODModule *  | 
2319  |  | SECMOD_LoadModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)  | 
2320  | 0  | { | 
2321  | 0  |     SECMODModule *module = NULL;  | 
2322  | 0  |     SECMODModule *oldModule = NULL;  | 
2323  | 0  |     SECStatus rv;  | 
2324  |  |  | 
2325  |  |     /* initialize the underlying module structures */  | 
2326  | 0  |     SECMOD_Init();  | 
2327  |  | 
  | 
2328  | 0  |     module = secmod_NewModule();  | 
2329  | 0  |     if (module == NULL) { | 
2330  | 0  |         goto loser;  | 
2331  | 0  |     }  | 
2332  |  |  | 
2333  | 0  |     module->commonName = PORT_ArenaStrdup(module->arena, moduleName ? moduleName : "");  | 
2334  | 0  |     module->internal = PR_FALSE;  | 
2335  | 0  |     module->isFIPS = PR_FALSE;  | 
2336  |  |     /* if the system FIPS mode is enabled, force FIPS to be on */  | 
2337  | 0  |     if (SECMOD_GetSystemFIPSEnabled()) { | 
2338  | 0  |         module->isFIPS = PR_TRUE;  | 
2339  | 0  |     }  | 
2340  |  | 
  | 
2341  | 0  |     module->isCritical = PR_FALSE;  | 
2342  |  |     /* new field */  | 
2343  | 0  |     module->trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER;  | 
2344  |  |     /* new field */  | 
2345  | 0  |     module->cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER;  | 
2346  |  |     /* new field */  | 
2347  | 0  |     module->isModuleDB = PR_FALSE;  | 
2348  | 0  |     module->moduleDBOnly = PR_FALSE;  | 
2349  |  | 
  | 
2350  | 0  |     module->ssl[0] = 0;  | 
2351  | 0  |     module->ssl[1] = 0;  | 
2352  |  | 
  | 
2353  | 0  |     secmod_PrivateModuleCount++;  | 
2354  |  |  | 
2355  |  |     /* load it */  | 
2356  | 0  |     rv = secmod_LoadPKCS11ModuleFromFunction(module, &oldModule, fentry);  | 
2357  | 0  |     if (rv != SECSuccess) { | 
2358  | 0  |         goto loser;  | 
2359  | 0  |     }  | 
2360  |  |  | 
2361  |  |     /* if we just reload an old module, no need to add it to any lists.  | 
2362  |  |      * we simple release all our references */  | 
2363  | 0  |     if (oldModule) { | 
2364  |  |         /* This module already exists, don't link it anywhere. This  | 
2365  |  |          * will probably destroy this module */  | 
2366  | 0  |         SECMOD_DestroyModule(module);  | 
2367  | 0  |         return oldModule;  | 
2368  | 0  |     }  | 
2369  |  |  | 
2370  | 0  |     SECMOD_AddModuleToList(module);  | 
2371  |  |     /* handle any additional work here */  | 
2372  | 0  |     return module;  | 
2373  |  |  | 
2374  | 0  | loser:  | 
2375  | 0  |     if (module) { | 
2376  | 0  |         if (module->loaded) { | 
2377  | 0  |             SECMOD_UnloadModule(module);  | 
2378  | 0  |         }  | 
2379  | 0  |         SECMOD_AddModuleToUnloadList(module);  | 
2380  | 0  |     }  | 
2381  | 0  |     return module;  | 
2382  | 0  | }  | 
2383  |  |  | 
2384  |  | /*  | 
2385  |  |  * load a PKCS#11 module and add it to the default NSS trust domain  | 
2386  |  |  */  | 
2387  |  | SECMODModule *  | 
2388  |  | SECMOD_LoadUserModule(char *modulespec, SECMODModule *parent, PRBool recurse)  | 
2389  | 0  | { | 
2390  | 0  |     SECStatus rv = SECSuccess;  | 
2391  | 0  |     SECMODModule *newmod = SECMOD_LoadModule(modulespec, parent, recurse);  | 
2392  | 0  |     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();  | 
2393  |  | 
  | 
2394  | 0  |     if (newmod) { | 
2395  | 0  |         SECMOD_GetReadLock(moduleLock);  | 
2396  | 0  |         rv = STAN_AddModuleToDefaultTrustDomain(newmod);  | 
2397  | 0  |         SECMOD_ReleaseReadLock(moduleLock);  | 
2398  | 0  |         if (SECSuccess != rv) { | 
2399  | 0  |             SECMOD_DestroyModule(newmod);  | 
2400  | 0  |             return NULL;  | 
2401  | 0  |         }  | 
2402  | 0  |     }  | 
2403  | 0  |     return newmod;  | 
2404  | 0  | }  | 
2405  |  |  | 
2406  |  | SECMODModule *  | 
2407  |  | SECMOD_LoadUserModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)  | 
2408  | 0  | { | 
2409  | 0  |     SECStatus rv = SECSuccess;  | 
2410  | 0  |     SECMODModule *newmod = SECMOD_LoadModuleWithFunction(moduleName, fentry);  | 
2411  | 0  |     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();  | 
2412  |  | 
  | 
2413  | 0  |     if (newmod) { | 
2414  | 0  |         SECMOD_GetReadLock(moduleLock);  | 
2415  | 0  |         rv = STAN_AddModuleToDefaultTrustDomain(newmod);  | 
2416  | 0  |         SECMOD_ReleaseReadLock(moduleLock);  | 
2417  | 0  |         if (SECSuccess != rv) { | 
2418  | 0  |             SECMOD_DestroyModule(newmod);  | 
2419  | 0  |             return NULL;  | 
2420  | 0  |         }  | 
2421  | 0  |     }  | 
2422  | 0  |     return newmod;  | 
2423  | 0  | }  | 
2424  |  |  | 
2425  |  | /*  | 
2426  |  |  * remove the PKCS#11 module from the default NSS trust domain, call  | 
2427  |  |  * C_Finalize, and destroy the module structure  | 
2428  |  |  */  | 
2429  |  | SECStatus  | 
2430  |  | SECMOD_UnloadUserModule(SECMODModule *mod)  | 
2431  | 0  | { | 
2432  | 0  |     SECStatus rv = SECSuccess;  | 
2433  | 0  |     int atype = 0;  | 
2434  | 0  |     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();  | 
2435  | 0  |     if (!mod) { | 
2436  | 0  |         return SECFailure;  | 
2437  | 0  |     }  | 
2438  |  |  | 
2439  | 0  |     SECMOD_GetReadLock(moduleLock);  | 
2440  | 0  |     rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);  | 
2441  | 0  |     SECMOD_ReleaseReadLock(moduleLock);  | 
2442  | 0  |     if (SECSuccess != rv) { | 
2443  | 0  |         return SECFailure;  | 
2444  | 0  |     }  | 
2445  | 0  |     return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE);  | 
2446  | 0  | }  |