]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
Merge remote-tracking branch 'origin/mdb.master'
[openldap] / libraries / libldap / tls_m.c
1 /* tls_m.c - Handle tls/ssl using Mozilla NSS. */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2008-2013 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS: Initial version written by Howard Chu. 
17  * Additional support by Rich Megginson.
18  */
19
20 #include "portable.h"
21
22 #ifdef HAVE_MOZNSS
23
24 #include "ldap_config.h"
25
26 #include <stdio.h>
27
28 #if defined( HAVE_FCNTL_H )
29 #include <fcntl.h>
30 #endif
31
32 #include <ac/stdlib.h>
33 #include <ac/errno.h>
34 #include <ac/socket.h>
35 #include <ac/string.h>
36 #include <ac/ctype.h>
37 #include <ac/time.h>
38 #include <ac/unistd.h>
39 #include <ac/param.h>
40 #include <ac/dirent.h>
41
42 #include "ldap-int.h"
43 #include "ldap-tls.h"
44
45 #define READ_PASSWORD_FROM_STDIN
46 #define READ_PASSWORD_FROM_FILE
47
48 #ifdef READ_PASSWORD_FROM_STDIN
49 #include <termios.h> /* for echo on/off */
50 #endif
51
52 #include <nspr/nspr.h>
53 #include <nspr/private/pprio.h>
54 #include <nss/nss.h>
55 #include <nss/ssl.h>
56 #include <nss/sslerr.h>
57 #include <nss/sslproto.h>
58 #include <nss/pk11pub.h>
59 #include <nss/secerr.h>
60 #include <nss/keyhi.h>
61 #include <nss/secmod.h>
62 #include <nss/cert.h>
63
64 #undef NSS_VERSION_INT
65 #define NSS_VERSION_INT ((NSS_VMAJOR << 24) | (NSS_VMINOR << 16) | \
66         (NSS_VPATCH << 8) | NSS_VBUILD)
67
68 /* NSS 3.12.5 and later have NSS_InitContext */
69 #if NSS_VERSION_INT >= 0x030c0500
70 #define HAVE_NSS_INITCONTEXT 1
71 #endif
72
73 /* NSS 3.12.9 and later have SECMOD_RestartModules */
74 #if NSS_VERSION_INT >= 0x030c0900
75 #define HAVE_SECMOD_RESTARTMODULES 1
76 #endif
77
78 /* InitContext does not currently work in server mode */
79 /* #define INITCONTEXT_HACK 1 */
80
81 typedef struct tlsm_ctx {
82         PRFileDesc *tc_model;
83         int tc_refcnt;
84         int tc_unique; /* unique number associated with this ctx */
85         PRBool tc_verify_cert;
86         CERTCertDBHandle *tc_certdb;
87         PK11SlotInfo *tc_certdb_slot;
88         CERTCertificate *tc_certificate;
89         SECKEYPrivateKey *tc_private_key;
90         char *tc_pin_file;
91         struct ldaptls *tc_config;
92         int tc_is_server;
93         int tc_require_cert;
94         PRCallOnceType tc_callonce;
95         PRBool tc_using_pem;
96 #ifdef HAVE_NSS_INITCONTEXT
97         NSSInitContext *tc_initctx; /* the NSS context */
98 #endif
99         PK11GenericObject **tc_pem_objs; /* array of objects to free */
100         int tc_n_pem_objs; /* number of objects */
101         PRBool tc_warn_only; /* only warn of errors in validation */
102 #ifdef LDAP_R_COMPILE
103         ldap_pvt_thread_mutex_t tc_refmutex;
104 #endif
105 } tlsm_ctx;
106
107 typedef PRFileDesc tlsm_session;
108
109 static int tlsm_ctx_count;
110 #define TLSM_CERTDB_DESC_FMT "ldap(%d)"
111
112 static PRDescIdentity   tlsm_layer_id;
113
114 static const PRIOMethods tlsm_PR_methods;
115
116 #define CERTDB_NONE NULL
117 #define PREFIX_NONE NULL
118
119 #define PEM_LIBRARY     "nsspem"
120 #define PEM_MODULE      "PEM"
121 /* hash files for use with cacertdir have this file name suffix */
122 #define PEM_CA_HASH_FILE_SUFFIX ".0"
123 #define PEM_CA_HASH_FILE_SUFFIX_LEN 2
124
125 static SECMODModule *pem_module;
126
127 #define DEFAULT_TOKEN_NAME "default"
128 #define TLSM_PEM_SLOT_CACERTS "PEM Token #0"
129 #define TLSM_PEM_SLOT_CERTS "PEM Token #1"
130
131 #define PK11_SETATTRS(x,id,v,l) (x).type = (id); \
132                 (x).pValue=(v); (x).ulValueLen = (l);
133
134 /* forward declaration */
135 static int tlsm_init( void );
136
137 #ifdef LDAP_R_COMPILE
138
139 /* it doesn't seem guaranteed that a client will call
140    tlsm_thr_init in a non-threaded context - so we have
141    to wrap the mutex creation in a prcallonce
142 */
143 static ldap_pvt_thread_mutex_t tlsm_ctx_count_mutex;
144 static ldap_pvt_thread_mutex_t tlsm_init_mutex;
145 static ldap_pvt_thread_mutex_t tlsm_pem_mutex;
146 static PRCallOnceType tlsm_init_mutex_callonce = {0,0};
147
148 static PRStatus PR_CALLBACK
149 tlsm_thr_init_callonce( void )
150 {
151         if ( ldap_pvt_thread_mutex_init( &tlsm_ctx_count_mutex ) ) {
152                 Debug( LDAP_DEBUG_ANY,
153                            "TLS: could not create mutex for context counter: %d\n", errno, 0, 0 );
154                 return PR_FAILURE;
155         }
156
157         if ( ldap_pvt_thread_mutex_init( &tlsm_init_mutex ) ) {
158                 Debug( LDAP_DEBUG_ANY,
159                            "TLS: could not create mutex for moznss initialization: %d\n", errno, 0, 0 );
160                 return PR_FAILURE;
161         }
162
163         if ( ldap_pvt_thread_mutex_init( &tlsm_pem_mutex ) ) {
164                 Debug( LDAP_DEBUG_ANY,
165                            "TLS: could not create mutex for PEM module: %d\n", errno, 0, 0 );
166                 return PR_FAILURE;
167         }
168
169         return PR_SUCCESS;
170 }
171
172 static void
173 tlsm_thr_init( void )
174 {
175     ( void )PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce );
176 }
177
178 #endif /* LDAP_R_COMPILE */
179
180 static const char *
181 tlsm_dump_cipher_info(PRFileDesc *fd)
182 {
183         PRUint16 ii;
184
185         for (ii = 0; ii < SSL_NumImplementedCiphers; ++ii) {
186                 PRInt32 cipher = (PRInt32)SSL_ImplementedCiphers[ii];
187                 PRBool enabled = PR_FALSE;
188                 PRInt32 policy = 0;
189                 SSLCipherSuiteInfo info;
190
191                 if (fd) {
192                         SSL_CipherPrefGet(fd, cipher, &enabled);
193                 } else {
194                         SSL_CipherPrefGetDefault(cipher, &enabled);
195                 }
196                 SSL_CipherPolicyGet(cipher, &policy);
197                 SSL_GetCipherSuiteInfo(cipher, &info, (PRUintn)sizeof(info));
198                 Debug( LDAP_DEBUG_TRACE,
199                            "TLS: cipher: %d - %s, enabled: %d, ",
200                            info.cipherSuite, info.cipherSuiteName, enabled );
201                 Debug( LDAP_DEBUG_TRACE,
202                            "policy: %d\n", policy, 0, 0 );
203         }
204
205         return "";
206 }
207
208 /* Cipher definitions */
209 typedef struct {
210         char *ossl_name;    /* The OpenSSL cipher name */
211         int num;            /* The cipher id */
212         int attr;           /* cipher attributes: algorithms, etc */
213         int version;        /* protocol version valid for this cipher */
214         int bits;           /* bits of strength */
215         int alg_bits;       /* bits of the algorithm */
216         int strength;       /* LOW, MEDIUM, HIGH */
217         int enabled;        /* Enabled by default? */
218 } cipher_properties;
219
220 /* cipher attributes  */
221 #define SSL_kRSA  0x00000001L
222 #define SSL_aRSA  0x00000002L
223 #define SSL_aDSS  0x00000004L
224 #define SSL_DSS   SSL_aDSS
225 #define SSL_eNULL 0x00000008L
226 #define SSL_DES   0x00000010L
227 #define SSL_3DES  0x00000020L
228 #define SSL_RC4   0x00000040L
229 #define SSL_RC2   0x00000080L
230 #define SSL_AES   0x00000100L
231 #define SSL_MD5   0x00000200L
232 #define SSL_SHA1  0x00000400L
233 #define SSL_SHA   SSL_SHA1
234 #define SSL_RSA   (SSL_kRSA|SSL_aRSA)
235
236 /* cipher strength */
237 #define SSL_NULL      0x00000001L
238 #define SSL_EXPORT40  0x00000002L
239 #define SSL_EXPORT56  0x00000004L
240 #define SSL_LOW       0x00000008L
241 #define SSL_MEDIUM    0x00000010L
242 #define SSL_HIGH      0x00000020L
243
244 #define SSL2  0x00000001L
245 #define SSL3  0x00000002L
246 /* OpenSSL treats SSL3 and TLSv1 the same */
247 #define TLS1  SSL3
248
249 /* Cipher translation */
250 static cipher_properties ciphers_def[] = {
251         /* SSL 2 ciphers */
252         {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, 168, 168, SSL_HIGH, SSL_ALLOWED},
253         {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
254         {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
255         {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, 56, 56, SSL_LOW, SSL_ALLOWED},
256         {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
257         {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
258
259         /* SSL3 ciphers */
260         {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
261         {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
262         {"DES-CBC3-SHA", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, 168, 168, SSL_HIGH, SSL_ALLOWED},
263         {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, 56, 56, SSL_LOW, SSL_ALLOWED},
264         {"EXP-RC4-MD5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
265         {"EXP-RC2-CBC-MD5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, 0, 0, SSL_EXPORT40, SSL_ALLOWED},
266         {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
267         {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
268
269         /* TLSv1 ciphers */
270         {"EXP1024-DES-CBC-SHA", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED},
271         {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED},
272         {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 128, 128, SSL_HIGH, SSL_ALLOWED},
273         {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 256, 256, SSL_HIGH, SSL_ALLOWED},
274 };
275
276 #define ciphernum (sizeof(ciphers_def)/sizeof(cipher_properties))
277
278 /* given err which is the current errno, calls PR_SetError with
279    the corresponding NSPR error code */
280 static void 
281 tlsm_map_error(int err)
282 {
283         PRErrorCode prError;
284
285         switch ( err ) {
286         case EACCES:
287                 prError = PR_NO_ACCESS_RIGHTS_ERROR;
288                 break;
289         case EADDRINUSE:
290                 prError = PR_ADDRESS_IN_USE_ERROR;
291                 break;
292         case EADDRNOTAVAIL:
293                 prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
294                 break;
295         case EAFNOSUPPORT:
296                 prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
297                 break;
298         case EAGAIN:
299                 prError = PR_WOULD_BLOCK_ERROR;
300                 break;
301         /*
302          * On QNX and Neutrino, EALREADY is defined as EBUSY.
303          */
304 #if EALREADY != EBUSY
305         case EALREADY:
306                 prError = PR_ALREADY_INITIATED_ERROR;
307                 break;
308 #endif
309         case EBADF:
310                 prError = PR_BAD_DESCRIPTOR_ERROR;
311                 break;
312 #ifdef EBADMSG
313         case EBADMSG:
314                 prError = PR_IO_ERROR;
315                 break;
316 #endif
317         case EBUSY:
318                 prError = PR_FILESYSTEM_MOUNTED_ERROR;
319                 break;
320         case ECONNABORTED:
321                 prError = PR_CONNECT_ABORTED_ERROR;
322                 break;
323         case ECONNREFUSED:
324                 prError = PR_CONNECT_REFUSED_ERROR;
325                 break;
326         case ECONNRESET:
327                 prError = PR_CONNECT_RESET_ERROR;
328                 break;
329         case EDEADLK:
330                 prError = PR_DEADLOCK_ERROR;
331                 break;
332 #ifdef EDIRCORRUPTED
333         case EDIRCORRUPTED:
334                 prError = PR_DIRECTORY_CORRUPTED_ERROR;
335                 break;
336 #endif
337 #ifdef EDQUOT
338         case EDQUOT:
339                 prError = PR_NO_DEVICE_SPACE_ERROR;
340                 break;
341 #endif
342         case EEXIST:
343                 prError = PR_FILE_EXISTS_ERROR;
344                 break;
345         case EFAULT:
346                 prError = PR_ACCESS_FAULT_ERROR;
347                 break;
348         case EFBIG:
349                 prError = PR_FILE_TOO_BIG_ERROR;
350                 break;
351         case EHOSTUNREACH:
352                 prError = PR_HOST_UNREACHABLE_ERROR;
353                 break;
354         case EINPROGRESS:
355                 prError = PR_IN_PROGRESS_ERROR;
356                 break;
357         case EINTR:
358                 prError = PR_PENDING_INTERRUPT_ERROR;
359                 break;
360         case EINVAL:
361                 prError = PR_INVALID_ARGUMENT_ERROR;
362                 break;
363         case EIO:
364                 prError = PR_IO_ERROR;
365                 break;
366         case EISCONN:
367                 prError = PR_IS_CONNECTED_ERROR;
368                 break;
369         case EISDIR:
370                 prError = PR_IS_DIRECTORY_ERROR;
371                 break;
372         case ELOOP:
373                 prError = PR_LOOP_ERROR;
374                 break;
375         case EMFILE:
376                 prError = PR_PROC_DESC_TABLE_FULL_ERROR;
377                 break;
378         case EMLINK:
379                 prError = PR_MAX_DIRECTORY_ENTRIES_ERROR;
380                 break;
381         case EMSGSIZE:
382                 prError = PR_INVALID_ARGUMENT_ERROR;
383                 break;
384 #ifdef EMULTIHOP
385         case EMULTIHOP:
386                 prError = PR_REMOTE_FILE_ERROR;
387                 break;
388 #endif
389         case ENAMETOOLONG:
390                 prError = PR_NAME_TOO_LONG_ERROR;
391                 break;
392         case ENETUNREACH:
393                 prError = PR_NETWORK_UNREACHABLE_ERROR;
394                 break;
395         case ENFILE:
396                 prError = PR_SYS_DESC_TABLE_FULL_ERROR;
397                 break;
398         /*
399          * On SCO OpenServer 5, ENOBUFS is defined as ENOSR.
400          */
401 #if defined(ENOBUFS) && (ENOBUFS != ENOSR)
402         case ENOBUFS:
403                 prError = PR_INSUFFICIENT_RESOURCES_ERROR;
404                 break;
405 #endif
406         case ENODEV:
407                 prError = PR_FILE_NOT_FOUND_ERROR;
408                 break;
409         case ENOENT:
410                 prError = PR_FILE_NOT_FOUND_ERROR;
411                 break;
412         case ENOLCK:
413                 prError = PR_FILE_IS_LOCKED_ERROR;
414                 break;
415 #ifdef ENOLINK 
416         case ENOLINK:
417                 prError = PR_REMOTE_FILE_ERROR;
418                 break;
419 #endif
420         case ENOMEM:
421                 prError = PR_OUT_OF_MEMORY_ERROR;
422                 break;
423         case ENOPROTOOPT:
424                 prError = PR_INVALID_ARGUMENT_ERROR;
425                 break;
426         case ENOSPC:
427                 prError = PR_NO_DEVICE_SPACE_ERROR;
428                 break;
429 #ifdef ENOSR
430         case ENOSR:
431                 prError = PR_INSUFFICIENT_RESOURCES_ERROR;
432                 break;
433 #endif
434         case ENOTCONN:
435                 prError = PR_NOT_CONNECTED_ERROR;
436                 break;
437         case ENOTDIR:
438                 prError = PR_NOT_DIRECTORY_ERROR;
439                 break;
440         case ENOTSOCK:
441                 prError = PR_NOT_SOCKET_ERROR;
442                 break;
443         case ENXIO:
444                 prError = PR_FILE_NOT_FOUND_ERROR;
445                 break;
446         case EOPNOTSUPP:
447                 prError = PR_NOT_TCP_SOCKET_ERROR;
448                 break;
449 #ifdef EOVERFLOW
450         case EOVERFLOW:
451                 prError = PR_BUFFER_OVERFLOW_ERROR;
452                 break;
453 #endif
454         case EPERM:
455                 prError = PR_NO_ACCESS_RIGHTS_ERROR;
456                 break;
457         case EPIPE:
458                 prError = PR_CONNECT_RESET_ERROR;
459                 break;
460 #ifdef EPROTO
461         case EPROTO:
462                 prError = PR_IO_ERROR;
463                 break;
464 #endif
465         case EPROTONOSUPPORT:
466                 prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
467                 break;
468         case EPROTOTYPE:
469                 prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
470                 break;
471         case ERANGE:
472                 prError = PR_INVALID_METHOD_ERROR;
473                 break;
474         case EROFS:
475                 prError = PR_READ_ONLY_FILESYSTEM_ERROR;
476                 break;
477         case ESPIPE:
478                 prError = PR_INVALID_METHOD_ERROR;
479                 break;
480         case ETIMEDOUT:
481                 prError = PR_IO_TIMEOUT_ERROR;
482                 break;
483 #if EWOULDBLOCK != EAGAIN
484         case EWOULDBLOCK:
485                 prError = PR_WOULD_BLOCK_ERROR;
486                 break;
487 #endif
488         case EXDEV:
489                 prError = PR_NOT_SAME_DEVICE_ERROR;
490                 break;
491         default:
492                 prError = PR_UNKNOWN_ERROR;
493                 break;
494         }
495         PR_SetError( prError, err );
496 }
497
498 /*
499  * cipher_list is an integer array with the following values:
500  *   -1: never enable this cipher
501  *    0: cipher disabled
502  *    1: cipher enabled
503  */
504 static int
505 nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum])
506 {
507         int i;
508         char *cipher;
509         char *ciphers;
510         char *ciphertip;
511         int action;
512         int rv;
513
514         /* All disabled to start */
515         for (i=0; i<ciphernum; i++)
516                 cipher_list[i] = 0;
517
518         ciphertip = strdup(cipherstr);
519         cipher = ciphers = ciphertip;
520
521         while (ciphers && (strlen(ciphers))) {
522                 while ((*cipher) && (isspace(*cipher)))
523                         ++cipher;
524
525                 action = 1;
526                 switch(*cipher) {
527                 case '+': /* Add something */
528                         action = 1;
529                         cipher++;
530                         break;
531                 case '-': /* Subtract something */
532                         action = 0;
533                         cipher++;
534                         break;
535                 case '!':  /* Disable something */
536                         action = -1;
537                         cipher++;
538                         break;
539                 default:
540                         /* do nothing */
541                         break;
542                 }
543
544                 if ((ciphers = strchr(cipher, ':'))) {
545                         *ciphers++ = '\0';
546                 }
547
548                 /* Do the easy one first */
549                 if (!strcmp(cipher, "ALL")) {
550                         for (i=0; i<ciphernum; i++) {
551                                 if (!(ciphers_def[i].attr & SSL_eNULL))
552                                         cipher_list[i] = action;
553                         }
554                 } else if (!strcmp(cipher, "COMPLEMENTOFALL")) {
555                         for (i=0; i<ciphernum; i++) {
556                                 if ((ciphers_def[i].attr & SSL_eNULL))
557                                         cipher_list[i] = action;
558                         }
559                 } else if (!strcmp(cipher, "DEFAULT")) {
560                         for (i=0; i<ciphernum; i++) {
561                                 cipher_list[i] = ciphers_def[i].enabled == SSL_ALLOWED ? 1 : 0;
562                         }
563                 } else {
564                         int mask = 0;
565                         int strength = 0;
566                         int protocol = 0;
567                         char *c;
568
569                         c = cipher;
570                         while (c && (strlen(c))) {
571
572                                 if ((c = strchr(cipher, '+'))) {
573                                         *c++ = '\0';
574                                 }
575
576                                 if (!strcmp(cipher, "RSA")) {
577                                         mask |= SSL_RSA;
578                                 } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) {
579                                         mask |= SSL_eNULL;
580                                 } else if (!strcmp(cipher, "AES")) {
581                                         mask |= SSL_AES;
582                                 } else if (!strcmp(cipher, "3DES")) {
583                                         mask |= SSL_3DES;
584                                 } else if (!strcmp(cipher, "DES")) {
585                                         mask |= SSL_DES;
586                                 } else if (!strcmp(cipher, "RC4")) {
587                                         mask |= SSL_RC4;
588                                 } else if (!strcmp(cipher, "RC2")) {
589                                         mask |= SSL_RC2;
590                                 } else if (!strcmp(cipher, "MD5")) {
591                                         mask |= SSL_MD5;
592                                 } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) {
593                                         mask |= SSL_SHA1;
594                                 } else if (!strcmp(cipher, "SSLv2")) {
595                                         protocol |= SSL2;
596                                 } else if (!strcmp(cipher, "SSLv3")) {
597                                         protocol |= SSL3;
598                                 } else if (!strcmp(cipher, "TLSv1")) {
599                                         protocol |= TLS1;
600                                 } else if (!strcmp(cipher, "HIGH")) {
601                                         strength |= SSL_HIGH;
602                                 } else if (!strcmp(cipher, "MEDIUM")) {
603                                         strength |= SSL_MEDIUM;
604                                 } else if (!strcmp(cipher, "LOW")) {
605                                         strength |= SSL_LOW;
606                                 } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) {
607                                         strength |= SSL_EXPORT40|SSL_EXPORT56;
608                                 } else if (!strcmp(cipher, "EXPORT40")) {
609                                         strength |= SSL_EXPORT40;
610                                 } else if (!strcmp(cipher, "EXPORT56")) {
611                                         strength |= SSL_EXPORT56;
612                                 }
613
614                                 if (c)
615                                         cipher = c;
616
617                         } /* while */
618
619                         /* If we have a mask, apply it. If not then perhaps they provided
620                          * a specific cipher to enable.
621                          */
622                         if (mask || strength || protocol) {
623                                 for (i=0; i<ciphernum; i++) {
624                                         if (((ciphers_def[i].attr & mask) ||
625                                                  (ciphers_def[i].strength & strength) ||
626                                                  (ciphers_def[i].version & protocol)) &&
627                                                 (cipher_list[i] != -1)) {
628                                                 /* Enable the NULL ciphers only if explicity
629                                                  * requested */
630                                                 if (ciphers_def[i].attr & SSL_eNULL) {
631                                                         if (mask & SSL_eNULL)
632                                                                 cipher_list[i] = action;
633                                                 } else
634                                                         cipher_list[i] = action;
635                                         }
636                                 }
637                         } else {
638                                 for (i=0; i<ciphernum; i++) {
639                                         if (!strcmp(ciphers_def[i].ossl_name, cipher) &&
640                                                 cipher_list[i] != -1)
641                                                 cipher_list[i] = action;
642                                 }
643                         }
644                 }
645
646                 if (ciphers)
647                         cipher = ciphers;
648         }
649
650         /* See if any ciphers were enabled */
651         rv = 0;
652         for (i=0; i<ciphernum; i++) {
653                 if (cipher_list[i] == 1)
654                         rv = 1;
655         }
656
657         free(ciphertip);
658
659         return rv;
660 }
661
662 static int
663 tlsm_parse_ciphers(tlsm_ctx *ctx, const char *str)
664 {
665         int cipher_state[ciphernum];
666         int rv, i;
667
668         if (!ctx)
669                 return 0;
670
671         rv = nss_parse_ciphers(str, cipher_state);
672
673         if (rv) {
674                 /* First disable everything */
675                 for (i = 0; i < SSL_NumImplementedCiphers; i++)
676                         SSL_CipherPrefSet(ctx->tc_model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
677
678                 /* Now enable what was requested */
679                 for (i=0; i<ciphernum; i++) {
680                         SSLCipherSuiteInfo suite;
681                         PRBool enabled;
682
683                         if (SSL_GetCipherSuiteInfo(ciphers_def[i].num, &suite, sizeof suite)
684                                 == SECSuccess) {
685                                 enabled = cipher_state[i] < 0 ? 0 : cipher_state[i];
686                                 if (enabled == SSL_ALLOWED) {
687                                         if (PK11_IsFIPS() && !suite.isFIPS)    
688                                                 enabled = SSL_NOT_ALLOWED;
689                                 }
690                                 SSL_CipherPrefSet(ctx->tc_model, ciphers_def[i].num, enabled);
691                         }
692                 }
693         }
694
695         return rv == 1 ? 0 : -1;
696 }
697
698 static SECStatus
699 tlsm_bad_cert_handler(void *arg, PRFileDesc *ssl)
700 {
701         SECStatus success = SECSuccess;
702         PRErrorCode err;
703         tlsm_ctx *ctx = (tlsm_ctx *)arg;
704
705         if (!ssl || !ctx) {
706                 return SECFailure;
707         }
708
709         err = PORT_GetError();
710
711         switch (err) {
712         case SEC_ERROR_UNTRUSTED_ISSUER:
713         case SEC_ERROR_UNKNOWN_ISSUER:
714         case SEC_ERROR_EXPIRED_CERTIFICATE:
715         case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
716                 if (ctx->tc_verify_cert) {
717                         success = SECFailure;
718                 }
719                 break;
720         /* we bypass NSS's hostname checks and do our own */
721         case SSL_ERROR_BAD_CERT_DOMAIN:
722                 break;
723         default:
724                 success = SECFailure;
725                 break;
726         }
727
728         return success;
729 }
730
731 static const char *
732 tlsm_dump_security_status(PRFileDesc *fd)
733 {
734         char * cp;      /* bulk cipher name */
735         char * ip;      /* cert issuer DN */
736         char * sp;      /* cert subject DN */
737         int    op;      /* High, Low, Off */
738         int    kp0;     /* total key bits */
739         int    kp1;     /* secret key bits */
740         SSL3Statistics * ssl3stats = SSL_GetStatistics();
741
742         SSL_SecurityStatus( fd, &op, &cp, &kp0, &kp1, &ip, &sp );
743         Debug( LDAP_DEBUG_TRACE,
744                    "TLS certificate verification: subject: %s, issuer: %s, cipher: %s, ",
745                    sp ? sp : "-unknown-", ip ? ip : "-unknown-", cp ? cp : "-unknown-" );
746         PR_Free(cp);
747         PR_Free(ip);
748         PR_Free(sp);
749         Debug( LDAP_DEBUG_TRACE,
750                    "security level: %s, secret key bits: %d, total key bits: %d, ",
751                    ((op == SSL_SECURITY_STATUS_ON_HIGH) ? "high" :
752                         ((op == SSL_SECURITY_STATUS_ON_LOW) ? "low" : "off")),
753                    kp1, kp0 );
754
755         Debug( LDAP_DEBUG_TRACE,
756                    "cache hits: %ld, cache misses: %ld, cache not reusable: %ld\n",
757                    ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
758                    ssl3stats->hch_sid_cache_not_ok );
759
760         return "";
761 }
762
763 static void
764 tlsm_handshake_complete_cb( PRFileDesc *fd, void *client_data )
765 {
766         tlsm_dump_security_status( fd );
767 }
768
769 #ifdef READ_PASSWORD_FROM_FILE
770 static char *
771 tlsm_get_pin_from_file(const char *token_name, tlsm_ctx *ctx)
772 {
773         char *pwdstr = NULL;
774         char *contents = NULL;
775         char *lasts = NULL;
776         char *line = NULL;
777         char *candidate = NULL;
778         PRFileInfo file_info;
779         PRFileDesc *pwd_fileptr = PR_Open( ctx->tc_pin_file, PR_RDONLY, 00400 );
780
781         /* open the password file */
782         if ( !pwd_fileptr ) {
783                 PRErrorCode errcode = PR_GetError();
784                 Debug( LDAP_DEBUG_ANY,
785                        "TLS: could not open security pin file %s - error %d:%s.\n",
786                        ctx->tc_pin_file, errcode,
787                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
788                 goto done;
789         }
790
791         /* get the file size */
792         if ( PR_SUCCESS != PR_GetFileInfo( ctx->tc_pin_file, &file_info ) ) {
793                 PRErrorCode errcode = PR_GetError();
794                 Debug( LDAP_DEBUG_ANY,
795                        "TLS: could not get file info from pin file %s - error %d:%s.\n",
796                        ctx->tc_pin_file, errcode,
797                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
798                 goto done;
799         }
800
801         /* create a buffer to hold the file contents */
802         if ( !( contents = PR_CALLOC( file_info.size + 1 ) ) ) {
803                 PRErrorCode errcode = PR_GetError();
804                 Debug( LDAP_DEBUG_ANY,
805                        "TLS: could not alloc a buffer for contents of pin file %s - error %d:%s.\n",
806                        ctx->tc_pin_file, errcode,
807                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
808                 goto done;
809         }
810
811         /* read file into the buffer */
812         if( PR_Read( pwd_fileptr, contents, file_info.size ) <= 0 ) {
813                 PRErrorCode errcode = PR_GetError();
814                 Debug( LDAP_DEBUG_ANY,
815                        "TLS: could not read the file contents from pin file %s - error %d:%s.\n",
816                        ctx->tc_pin_file, errcode,
817                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
818                 goto done;
819         }
820
821         /* format is [tokenname:]password EOL [tokenname:]password EOL ... */
822         /* if you want to use a password containing a colon character, use
823            the special tokenname "default" */
824         for ( line = PL_strtok_r( contents, "\r\n", &lasts ); line;
825               line = PL_strtok_r( NULL, "\r\n", &lasts ) ) {
826                 char *colon;
827
828                 if ( !*line ) {
829                         continue; /* skip blank lines */
830                 }
831                 colon = PL_strchr( line, ':' );
832                 if ( colon ) {
833                         if ( *(colon + 1) && token_name &&
834                              !PL_strncmp( token_name, line, colon-line ) ) {
835                                 candidate = colon + 1; /* found a definite match */
836                                 break;
837                         } else if ( !PL_strncmp( DEFAULT_TOKEN_NAME, line, colon-line ) ) {
838                                 candidate = colon + 1; /* found possible match */
839                         }
840                 } else { /* no token name */
841                         candidate = line;
842                 }
843         }
844 done:
845         if ( pwd_fileptr ) {
846                 PR_Close( pwd_fileptr );
847         }
848         if ( candidate ) {
849                 pwdstr = PL_strdup( candidate );
850         }
851         PL_strfree( contents );
852
853         return pwdstr;
854 }
855 #endif /* READ_PASSWORD_FROM_FILE */
856
857 #ifdef READ_PASSWORD_FROM_STDIN
858 /*
859  * Turn the echoing off on a tty.
860  */
861 static void
862 echoOff(int fd)
863 {
864         if ( isatty( fd ) ) {
865                 struct termios tio;
866                 tcgetattr( fd, &tio );
867                 tio.c_lflag &= ~ECHO;
868                 tcsetattr( fd, TCSAFLUSH, &tio );
869         }
870 }
871
872 /*
873  * Turn the echoing on on a tty.
874  */
875 static void
876 echoOn(int fd)
877 {
878         if ( isatty( fd ) ) {
879                 struct termios tio;
880                 tcgetattr( fd, &tio );
881                 tio.c_lflag |= ECHO;
882                 tcsetattr( fd, TCSAFLUSH, &tio );
883                 tcsetattr( fd, TCSAFLUSH, &tio );
884         }
885 }
886 #endif /* READ_PASSWORD_FROM_STDIN */
887
888 /*
889  * This does the actual work of reading the pin/password/pass phrase
890  */
891 static char *
892 tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx)
893 {
894         char *token_name = NULL;
895         char *pwdstr = NULL;
896
897         token_name = PK11_GetTokenName( slot );
898 #ifdef READ_PASSWORD_FROM_FILE
899         /* Try to get the passwords from the password file if it exists.
900          * THIS IS UNSAFE and is provided for convenience only. Without this
901          * capability the server would have to be started in foreground mode
902          * if using an encrypted key.
903          */
904         if ( ctx && ctx->tc_pin_file ) {
905                 pwdstr = tlsm_get_pin_from_file( token_name, ctx );
906                 if ( retry && pwdstr != NULL )
907                         return NULL;
908         }
909 #endif /* RETRIEVE_PASSWORD_FROM_FILE */
910 #ifdef READ_PASSWORD_FROM_STDIN
911         if ( !pwdstr ) {
912                 int infd = PR_FileDesc2NativeHandle( PR_STDIN );
913                 int isTTY = isatty( infd );
914                 unsigned char phrase[200];
915                 char *dummy;
916                 /* Prompt for password */
917                 if ( isTTY ) {
918                         fprintf( stdout,
919                                  "Please enter pin, password, or pass phrase for security token '%s': ",
920                                  token_name ? token_name : DEFAULT_TOKEN_NAME );
921                         echoOff( infd );
922                 }
923                 dummy = fgets( (char*)phrase, sizeof(phrase), stdin );
924                 (void) dummy;
925                 if ( isTTY ) {
926                         fprintf( stdout, "\n" );
927                         echoOn( infd );
928                 }
929                 /* stomp on newline */
930                 phrase[strlen((char*)phrase)-1] = 0;
931
932                 pwdstr = PL_strdup( (char*)phrase );
933         }
934
935 #endif /* READ_PASSWORD_FROM_STDIN */
936         return pwdstr;
937 }
938
939 /*
940  * PKCS11 devices (including the internal softokn cert/key database)
941  * may be protected by a pin or password or even pass phrase
942  * MozNSS needs a way for the user to provide that
943  */
944 static char *
945 tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg)
946 {
947         tlsm_ctx *ctx = (tlsm_ctx *)arg;
948
949         return tlsm_get_pin( slot, retry, ctx );
950 }
951
952 static char *
953 tlsm_ctx_subject_name(tlsm_ctx *ctx)
954 {
955         if ( !ctx || !ctx->tc_certificate )
956                 return "(unknown)";
957
958         return ctx->tc_certificate->subjectName;
959 }
960
961 static SECStatus
962 tlsm_get_basic_constraint_extension( CERTCertificate *cert,
963                                                                          CERTBasicConstraints *cbcval )
964 {
965         SECItem encodedVal = { 0, NULL };
966         SECStatus rc;
967
968         rc = CERT_FindCertExtension( cert, SEC_OID_X509_BASIC_CONSTRAINTS,
969                                                                  &encodedVal);
970         if ( rc != SECSuccess ) {
971                 return rc;
972         }
973
974         rc = CERT_DecodeBasicConstraintValue( cbcval, &encodedVal );
975
976         /* free the raw extension data */
977         PORT_Free( encodedVal.data );
978
979         return rc;
980 }
981
982 static PRBool
983 tlsm_cert_is_self_issued( CERTCertificate *cert )
984 {
985         /* A cert is self-issued if its subject and issuer are equal and
986          * both are of non-zero length. 
987          */
988         PRBool is_self_issued = cert &&
989                 (PRBool)SECITEM_ItemsAreEqual( &cert->derIssuer, 
990                                                                            &cert->derSubject ) &&
991                 cert->derSubject.len > 0;
992         return is_self_issued;
993 }
994
995 /*
996  * The private key for used certificate can be already unlocked by other
997  * thread or library. Find the unlocked key if possible.
998  */
999 static SECKEYPrivateKey *
1000 tlsm_find_unlocked_key( tlsm_ctx *ctx, void *pin_arg )
1001 {
1002         SECKEYPrivateKey *result = NULL;
1003
1004         PK11SlotList *slots = PK11_GetAllSlotsForCert( ctx->tc_certificate, NULL );
1005         if ( !slots ) {
1006                 PRErrorCode errcode = PR_GetError();
1007                 Debug( LDAP_DEBUG_ANY,
1008                                 "TLS: cannot get all slots for certificate '%s' (error %d: %s)",
1009                                 tlsm_ctx_subject_name( ctx ), errcode,
1010                                 PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1011                 return result;
1012         }
1013
1014         PK11SlotListElement *le;
1015         for ( le = slots->head; le; le = le->next ) {
1016                 PK11SlotInfo *slot = le->slot;
1017                 if ( PK11_IsLoggedIn( slot, NULL ) ) {
1018                         result = PK11_FindKeyByDERCert( slot, ctx->tc_certificate, pin_arg );
1019                         break;
1020                 }
1021         }
1022
1023         PK11_FreeSlotList( slots );
1024         return result;
1025 }
1026
1027 static SECStatus
1028 tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
1029                                  PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only,
1030                                  PRBool ignore_issuer )
1031 {
1032         CERTVerifyLog verifylog;
1033         SECStatus ret = SECSuccess;
1034         const char *name;
1035         int debug_level = LDAP_DEBUG_ANY;
1036
1037         if ( warn_only ) {
1038                 debug_level = LDAP_DEBUG_TRACE;
1039         }
1040
1041         /* the log captures information about every cert in the chain, so we can tell
1042            which cert caused the problem and what the problem was */
1043         memset( &verifylog, 0, sizeof( verifylog ) );
1044         verifylog.arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
1045         if ( verifylog.arena == NULL ) {
1046                 Debug( LDAP_DEBUG_ANY,
1047                            "TLS certificate verification: Out of memory for certificate verification logger\n",
1048                            0, 0, 0 );
1049                 return SECFailure;
1050         }
1051         ret = CERT_VerifyCertificate( handle, cert, checksig, certUsage, PR_Now(), pinarg, &verifylog,
1052                                                                   NULL );
1053         if ( ( name = cert->subjectName ) == NULL ) {
1054                 name = cert->nickname;
1055         }
1056         if ( verifylog.head == NULL ) {
1057                 /* it is possible for CERT_VerifyCertificate return with an error with no logging */
1058                 if ( ret != SECSuccess ) {
1059                         PRErrorCode errcode = PR_GetError();
1060                         Debug( debug_level,
1061                                    "TLS: certificate [%s] is not valid - error %d:%s.\n",
1062                                    name ? name : "(unknown)",
1063                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1064                 }
1065         } else {
1066                 const char *name;
1067                 CERTVerifyLogNode *node;
1068
1069                 ret = SECSuccess; /* reset */
1070                 node = verifylog.head;
1071                 while ( node ) {
1072                         if ( ( name = node->cert->subjectName ) == NULL ) {
1073                                 name = node->cert->nickname;
1074                         }
1075                         if ( node->error ) {
1076                                 /* NSS does not like CA certs that have the basic constraints extension
1077                                    with the CA flag set to FALSE - openssl doesn't check if the cert
1078                                    is self issued */
1079                                 if ( ( node->error == SEC_ERROR_CA_CERT_INVALID ) &&
1080                                          tlsm_cert_is_self_issued( node->cert ) ) {
1081
1082                                         PRErrorCode orig_error = PR_GetError();
1083                                         PRInt32 orig_oserror = PR_GetOSError();
1084
1085                                         CERTBasicConstraints basicConstraint;
1086                                         SECStatus rv = tlsm_get_basic_constraint_extension( node->cert, &basicConstraint );
1087                                         if ( ( rv == SECSuccess ) && ( basicConstraint.isCA == PR_FALSE ) ) {
1088                                                 Debug( LDAP_DEBUG_TRACE,
1089                                                            "TLS: certificate [%s] is not correct because it is a CA cert and the "
1090                                                            "BasicConstraint CA flag is set to FALSE - allowing for now, but "
1091                                                            "please fix your certs if possible\n", name, 0, 0 );
1092                                         } else { /* does not have basicconstraint, or some other error */
1093                                                 ret = SECFailure;
1094                                                 Debug( debug_level,
1095                                                            "TLS: certificate [%s] is not valid - CA cert is not valid\n",
1096                                                            name, 0, 0 );
1097                                         }
1098
1099                                         PR_SetError( orig_error, orig_oserror );
1100
1101                                 } else if ( warn_only || ( ignore_issuer && (
1102                                         node->error == SEC_ERROR_UNKNOWN_ISSUER ||
1103                                         node->error == SEC_ERROR_UNTRUSTED_ISSUER )
1104                                 ) ) {
1105                                         ret = SECSuccess;
1106                                         Debug( debug_level,
1107                                                    "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
1108                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1109                                 } else {
1110                                         ret = SECFailure;
1111                                         Debug( debug_level,
1112                                                    "TLS: certificate [%s] is not valid - error %ld:%s.\n",
1113                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1114                                 }
1115                         }
1116                         CERT_DestroyCertificate( node->cert );
1117                         node = node->next;
1118                 }
1119         }
1120
1121         PORT_FreeArena( verifylog.arena, PR_FALSE );
1122
1123         if ( ret == SECSuccess ) {
1124                 Debug( LDAP_DEBUG_TRACE,
1125                            "TLS: certificate [%s] is valid\n", name, 0, 0 );
1126         }
1127
1128         return ret;
1129 }
1130
1131 static SECStatus
1132 tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
1133                        PRBool checksig, PRBool isServer)
1134 {
1135         SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
1136         SECStatus ret = SECSuccess;
1137         CERTCertificate *peercert = SSL_PeerCertificate( fd );
1138         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1139
1140         ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
1141                                                         SSL_RevealPinArg( fd ),
1142                                                         checksig, certUsage, ctx->tc_warn_only, PR_FALSE );
1143         CERT_DestroyCertificate( peercert );
1144
1145         return ret;
1146 }
1147
1148 static SECStatus
1149 tlsm_nss_shutdown_cb( void *appData, void *nssData )
1150 {
1151         SECStatus rc = SECSuccess;
1152
1153         SSL_ShutdownServerSessionIDCache();
1154
1155         if ( pem_module ) {
1156                 SECMOD_UnloadUserModule( pem_module );
1157                 SECMOD_DestroyModule( pem_module );
1158                 pem_module = NULL;
1159         }
1160         return rc;
1161 }
1162
1163 static PRCallOnceType tlsm_register_shutdown_callonce = {0,0};
1164 static PRStatus PR_CALLBACK
1165 tlsm_register_nss_shutdown_cb( void )
1166 {
1167         if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb,
1168                                                                                          NULL ) ) {
1169                 return PR_SUCCESS;
1170         }
1171         return PR_FAILURE;
1172 }
1173
1174 static PRStatus
1175 tlsm_register_nss_shutdown( void )
1176 {
1177         return PR_CallOnce( &tlsm_register_shutdown_callonce,
1178                                                 tlsm_register_nss_shutdown_cb );
1179 }
1180
1181 static int
1182 tlsm_init_pem_module( void )
1183 {
1184         int rc = 0;
1185         char *fullname = NULL;
1186         char *configstring = NULL;
1187
1188         if ( pem_module ) {
1189                 return rc;
1190         }
1191
1192         /* not loaded - load it */
1193         /* get the system dependent library name */
1194         fullname = PR_GetLibraryName( NULL, PEM_LIBRARY );
1195         /* Load our PKCS#11 module */
1196         configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname );
1197         PL_strfree( fullname );
1198
1199         pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
1200         PR_smprintf_free( configstring );
1201
1202         if ( !pem_module || !pem_module->loaded ) {
1203                 if ( pem_module ) {
1204                         SECMOD_DestroyModule( pem_module );
1205                         pem_module = NULL;
1206                 }
1207                 rc = -1;
1208         }
1209
1210         return rc;
1211 }
1212
1213 static void
1214 tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
1215 {
1216         int idx = ctx->tc_n_pem_objs;
1217         ctx->tc_n_pem_objs++;
1218         ctx->tc_pem_objs = (PK11GenericObject **)
1219                 PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
1220         ctx->tc_pem_objs[idx] = obj;                                                                                                              
1221 }
1222
1223 static void
1224 tlsm_free_pem_objs( tlsm_ctx *ctx )
1225 {
1226         /* free in reverse order of allocation */
1227         while ( ctx->tc_n_pem_objs-- ) {
1228                 PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
1229                 ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
1230         }
1231         PORT_Free(ctx->tc_pem_objs);
1232         ctx->tc_pem_objs = NULL;
1233         ctx->tc_n_pem_objs = 0;
1234 }
1235
1236 static int
1237 tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
1238 {
1239         PK11SlotInfo *slot;
1240         PK11GenericObject *cert;
1241         CK_ATTRIBUTE attrs[4];
1242         CK_BBOOL cktrue = CK_TRUE;
1243         CK_BBOOL ckfalse = CK_FALSE;
1244         CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
1245         char *slotname;
1246         PRFileInfo fi;
1247         PRStatus status;
1248         SECItem certDER = { 0, NULL, 0 };
1249
1250         memset( &fi, 0, sizeof(fi) );
1251         status = PR_GetFileInfo( filename, &fi );
1252         if ( PR_SUCCESS != status) {
1253                 PRErrorCode errcode = PR_GetError();
1254                 Debug( LDAP_DEBUG_ANY,
1255                            "TLS: could not read certificate file %s - error %d:%s.\n",
1256                            filename, errcode,
1257                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1258                 return -1;
1259         }
1260
1261         if ( fi.type != PR_FILE_FILE ) {
1262                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1263                 Debug( LDAP_DEBUG_ANY,
1264                            "TLS: error: the certificate file %s is not a file.\n",
1265                            filename, 0 ,0 );
1266                 return -1;
1267         }
1268
1269         slotname = isca ? TLSM_PEM_SLOT_CACERTS : TLSM_PEM_SLOT_CERTS;
1270         slot = PK11_FindSlotByName( slotname );
1271
1272         if ( !slot ) {
1273                 PRErrorCode errcode = PR_GetError();
1274                 Debug( LDAP_DEBUG_ANY,
1275                            "TLS: could not find the slot for the certificate '%s' - error %d:%s.\n",
1276                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1277                 return -1;
1278         }
1279
1280         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
1281         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
1282         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *) filename, strlen( filename ) + 1 );
1283         PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof( CK_BBOOL ) );
1284
1285         cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ );
1286
1287         if ( !cert ) {
1288                 PRErrorCode errcode = PR_GetError();
1289                 Debug( LDAP_DEBUG_ANY,
1290                            "TLS: could not add the certificate '%s' - error %d:%s.\n",
1291                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1292                 PK11_FreeSlot( slot );
1293                 return -1;
1294         }
1295
1296         /* if not CA, we store the certificate in ctx->tc_certificate */
1297         if ( !isca ) {
1298                 if ( PK11_ReadRawAttribute( PK11_TypeGeneric, cert, CKA_VALUE, &certDER ) != SECSuccess ) {
1299                         PRErrorCode errcode = PR_GetError();
1300                         Debug( LDAP_DEBUG_ANY,
1301                                         "TLS: could not get DER of the '%s' certificate - error %d:%s.\n",
1302                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1303                         PK11_DestroyGenericObject( cert );
1304                         PK11_FreeSlot( slot );
1305                         return -1;
1306                 }
1307
1308                 ctx->tc_certificate = PK11_FindCertFromDERCertItem( slot, &certDER, NULL );
1309                 SECITEM_FreeItem( &certDER, PR_FALSE );
1310
1311                 if ( !ctx->tc_certificate ) {
1312                         PRErrorCode errcode = PR_GetError();
1313                         Debug( LDAP_DEBUG_ANY,
1314                                         "TLS: could not get certificate '%s' using DER - error %d:%s.\n",
1315                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1316                         PK11_DestroyGenericObject( cert );
1317                         PK11_FreeSlot( slot );
1318                         return -1;
1319                 }
1320         }
1321
1322         tlsm_add_pem_obj( ctx, cert );
1323
1324         PK11_FreeSlot( slot );
1325
1326         return 0;
1327 }
1328
1329 static int
1330 tlsm_ctx_load_private_key( tlsm_ctx *ctx )
1331 {
1332         if ( !ctx->tc_certificate )
1333                 return -1;
1334
1335         if ( ctx->tc_private_key )
1336                 return 0;
1337
1338         void *pin_arg = SSL_RevealPinArg( ctx->tc_model );
1339
1340         SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key( ctx, pin_arg );
1341         Debug( LDAP_DEBUG_ANY,
1342                         "TLS: %s unlocked certificate for certificate '%s'.\n",
1343                         unlocked_key ? "found" : "no", tlsm_ctx_subject_name( ctx ), 0 );
1344
1345         /* prefer unlocked key, then key from opened certdb, then any other */
1346         if ( unlocked_key )
1347                 ctx->tc_private_key = unlocked_key;
1348         else if ( ctx->tc_certdb_slot )
1349                 ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg );
1350         else
1351                 ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg );
1352
1353         if ( !ctx->tc_private_key ) {
1354                 PRErrorCode errcode = PR_GetError();
1355                 Debug(LDAP_DEBUG_ANY,
1356                                 "TLS: cannot find private key for certificate '%s' (error %d: %s)",
1357                                 tlsm_ctx_subject_name( ctx ), errcode,
1358                                 PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1359                 return -1;
1360         }
1361
1362         return 0;
1363 }
1364
1365 static int
1366 tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
1367 {
1368         PK11SlotInfo * slot = NULL;
1369         PK11GenericObject *key;
1370         CK_ATTRIBUTE attrs[3];
1371         CK_BBOOL cktrue = CK_TRUE;
1372         CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
1373         int retcode = 0;
1374         PRFileInfo fi;
1375         PRStatus status;
1376
1377         memset( &fi, 0, sizeof(fi) );
1378         status = PR_GetFileInfo( filename, &fi );
1379         if ( PR_SUCCESS != status) {
1380                 PRErrorCode errcode = PR_GetError();
1381                 Debug( LDAP_DEBUG_ANY,
1382                            "TLS: could not read key file %s - error %d:%s.\n",
1383                            filename, errcode,
1384                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1385                 return -1;
1386         }
1387
1388         if ( fi.type != PR_FILE_FILE ) {
1389                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1390                 Debug( LDAP_DEBUG_ANY,
1391                            "TLS: error: the key file %s is not a file.\n",
1392                            filename, 0 ,0 );
1393                 return -1;
1394         }
1395
1396         slot = PK11_FindSlotByName( TLSM_PEM_SLOT_CERTS );
1397
1398         if ( !slot ) {
1399                 PRErrorCode errcode = PR_GetError();
1400                 Debug( LDAP_DEBUG_ANY,
1401                            "TLS: could not find the slot for the private key '%s' - error %d:%s.\n",
1402                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1403                 return -1;
1404         }
1405
1406         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
1407         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
1408         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen( filename ) + 1 );
1409
1410         key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ );
1411
1412         if ( !key ) {
1413                 PRErrorCode errcode = PR_GetError();
1414                 Debug( LDAP_DEBUG_ANY,
1415                            "TLS: could not add the private key '%s' - error %d:%s.\n",
1416                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1417                 retcode = -1;
1418         } else {
1419                 tlsm_add_pem_obj( ctx, key );
1420                 retcode = 0;
1421
1422                 /* When adding an encrypted key the PKCS#11 will be set as removed */
1423                 /* This will force the token to be seen as re-inserted */
1424                 SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
1425                 PK11_IsPresent( slot );
1426         }
1427
1428         PK11_FreeSlot( slot );
1429
1430         return retcode;
1431 }
1432
1433 static int
1434 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
1435 {
1436         PRBool isca = PR_TRUE;
1437         PRStatus status = PR_SUCCESS;
1438         PRErrorCode errcode = PR_SUCCESS;
1439
1440         if ( !cacertfile && !cacertdir ) {
1441                 /* no checking - not good, but allowed */
1442                 return 0;
1443         }
1444
1445         if ( cacertfile ) {
1446                 int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca );
1447                 if ( rc ) {
1448                         errcode = PR_GetError();
1449                         Debug( LDAP_DEBUG_ANY,
1450                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1451                                    cacertfile, errcode,
1452                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1453                         /* failure with cacertfile is a hard failure even if cacertdir is
1454                            also specified and contains valid CA cert files */
1455                         status = PR_FAILURE;
1456                 } else {
1457                         Debug( LDAP_DEBUG_TRACE,
1458                                    "TLS: loaded CA certificate file %s.\n",
1459                                    cacertfile, 0, 0 );
1460                 }
1461         }
1462
1463         /* if cacertfile above failed, we will return failure, even
1464            if there is a valid CA cert in cacertdir - but we still
1465            process cacertdir in case the user has enabled trace level
1466            debugging so they can see the processing for cacertdir too */
1467         /* any cacertdir failures are "soft" failures - if the user specifies
1468            no cert checking, then we allow the tls/ssl to continue, no matter
1469            what was specified for cacertdir, or the contents of the directory
1470            - this is different behavior than that of cacertfile */
1471         if ( cacertdir ) {
1472                 PRFileInfo fi;
1473                 PRDir *dir;
1474                 PRDirEntry *entry;
1475                 PRStatus fistatus = PR_FAILURE;
1476
1477                 memset( &fi, 0, sizeof(fi) );
1478                 fistatus = PR_GetFileInfo( cacertdir, &fi );
1479                 if ( PR_SUCCESS != fistatus) {
1480                         errcode = PR_GetError();
1481                         Debug( LDAP_DEBUG_ANY,
1482                                    "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
1483                                    cacertdir, errcode,
1484                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1485                         goto done;
1486                 }
1487
1488                 if ( fi.type != PR_FILE_DIRECTORY ) {
1489                         Debug( LDAP_DEBUG_ANY,
1490                                    "TLS: error: the CA certificate directory %s is not a directory.\n",
1491                                    cacertdir, 0 ,0 );
1492                         goto done;
1493                 }
1494
1495                 dir = PR_OpenDir( cacertdir );
1496                 if ( NULL == dir ) {
1497                         errcode = PR_GetError();
1498                         Debug( LDAP_DEBUG_ANY,
1499                                    "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
1500                                    cacertdir, errcode,
1501                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1502                         goto done;
1503                 }
1504
1505                 do {
1506                         entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
1507                         if ( ( NULL != entry ) && ( NULL != entry->name ) ) {
1508                                 char *fullpath = NULL;
1509                                 char *ptr;
1510
1511                                 ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX );
1512                                 if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) {
1513                                         Debug( LDAP_DEBUG_TRACE,
1514                                                    "TLS: file %s does not end in [%s] - does not appear to be a CA certificate "
1515                                                    "directory file with a properly hashed file name - skipping.\n",
1516                                                    entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 );
1517                                         continue;
1518                                 }
1519                                 fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
1520                                 if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) {
1521                                         Debug( LDAP_DEBUG_TRACE,
1522                                                    "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
1523                                                    fullpath, cacertdir, 0 );
1524                                 } else {
1525                                         errcode = PR_GetError();
1526                                         Debug( LDAP_DEBUG_TRACE,
1527                                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1528                                                    fullpath, errcode,
1529                                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1530                                 }
1531                                 PR_smprintf_free( fullpath );
1532                         }
1533                 } while ( NULL != entry );
1534                 PR_CloseDir( dir );
1535         }
1536 done:
1537         if ( status != PR_SUCCESS ) {
1538                 return -1;
1539         }
1540
1541         return 0;
1542 }
1543
1544 /*
1545  * NSS supports having multiple cert/key databases in the same
1546  * directory, each one having a unique string prefix e.g.
1547  * slapd-01-cert8.db - the prefix here is "slapd-01-"
1548  * this function examines the given certdir - if it looks like
1549  * /path/to/directory/prefix it will return the
1550  * /path/to/directory part in realcertdir, and the prefix in prefix
1551  */
1552 static void
1553 tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
1554 {
1555         char sep = PR_GetDirectorySeparator();
1556         char *ptr = NULL;
1557         struct PRFileInfo prfi;
1558         PRStatus prc;
1559
1560         *realcertdir = (char *)certdir; /* default is the one passed in */
1561
1562         /* if certdir is not given, just return */
1563         if ( !certdir ) {
1564                 return;
1565         }
1566
1567         prc = PR_GetFileInfo( certdir, &prfi );
1568         /* if certdir exists (file or directory) then it cannot specify a prefix */
1569         if ( prc == PR_SUCCESS ) {
1570                 return;
1571         }
1572
1573         /* if certdir was given, and there is a '/' in certdir, see if there
1574            is anything after the last '/' - if so, assume it is the prefix */
1575         if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
1576                 *realcertdir = PL_strndup( certdir, ptr-certdir );
1577                 *prefix = PL_strdup( ptr+1 );
1578         }
1579
1580         return;
1581 }
1582
1583 /*
1584  * Currently mutiple MozNSS contexts share one certificate storage. When the
1585  * certdb is being opened, only new certificates are added to the storage.
1586  * When different databases are used, conflicting nicknames make the
1587  * certificate lookup by the nickname impossible. In addition a token
1588  * description might be prepended in certain conditions.
1589  *
1590  * In order to make the certificate lookup by nickname possible, we explicitly
1591  * open each database using SECMOD_OpenUserDB and assign it the token
1592  * description. The token description is generated using ctx->tc_unique value,
1593  * which is unique for each context.
1594  */
1595 static PK11SlotInfo *
1596 tlsm_init_open_certdb( tlsm_ctx *ctx, const char *dbdir, const char *prefix )
1597 {
1598         PK11SlotInfo *slot = NULL;
1599         char *token_desc = NULL;
1600         char *config = NULL;
1601
1602         token_desc = PR_smprintf( TLSM_CERTDB_DESC_FMT, ctx->tc_unique );
1603         config = PR_smprintf( "configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly",
1604                                                                                 dbdir, token_desc, prefix, prefix );
1605         Debug( LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0 );
1606
1607         slot = SECMOD_OpenUserDB( config );
1608         if ( !slot ) {
1609                 PRErrorCode errcode = PR_GetError();
1610                 Debug( LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode,
1611                                                         PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1612         }
1613
1614         if ( token_desc )
1615                 PR_smprintf_free( token_desc );
1616         if ( config )
1617                 PR_smprintf_free( config );
1618
1619         return slot;
1620 }
1621
1622 /*
1623  * This is the part of the init we defer until we get the
1624  * actual security configuration information.  This is
1625  * only called once, protected by a PRCallOnce
1626  * NOTE: This must be done before the first call to SSL_ImportFD,
1627  * especially the setting of the policy
1628  * NOTE: This must be called after fork()
1629  */
1630 static int
1631 tlsm_deferred_init( void *arg )
1632 {
1633         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1634         struct ldaptls *lt = ctx->tc_config;
1635         const char *securitydirs[3];
1636         int ii;
1637         int nn;
1638         PRErrorCode errcode = 1;
1639 #ifdef HAVE_NSS_INITCONTEXT
1640         NSSInitParameters initParams;
1641         NSSInitContext *initctx = NULL;
1642         PK11SlotInfo *certdb_slot = NULL;
1643 #endif
1644         SECStatus rc;
1645         int done = 0;
1646
1647 #ifdef HAVE_SECMOD_RESTARTMODULES
1648         /* NSS enforces the pkcs11 requirement that modules should be unloaded after
1649            a fork() - since there is no portable way to determine if NSS has been
1650            already initialized in a parent process, we just call SECMOD_RestartModules
1651            with force == FALSE - if the module has been unloaded due to a fork, it will
1652            be reloaded, otherwise, it is a no-op */
1653         if ( SECFailure == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) {
1654                 errcode = PORT_GetError();
1655                 if ( errcode != SEC_ERROR_NOT_INITIALIZED ) {
1656                         Debug( LDAP_DEBUG_TRACE,
1657                                    "TLS: could not restart the security modules: %d:%s\n",
1658                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1659                 } else {
1660                         errcode = 1;
1661                 }
1662         }
1663 #endif
1664
1665 #ifdef HAVE_NSS_INITCONTEXT
1666         memset( &initParams, 0, sizeof( initParams ) );
1667         initParams.length = sizeof( initParams );
1668 #endif /* HAVE_NSS_INITCONTEXT */
1669
1670 #ifdef LDAP_R_COMPILE
1671         if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) {
1672                 return -1;
1673         }
1674 #endif /* LDAP_R_COMPILE */
1675
1676 #ifndef HAVE_NSS_INITCONTEXT
1677         if ( !NSS_IsInitialized() ) {
1678 #endif /* HAVE_NSS_INITCONTEXT */
1679                 /*
1680                   MOZNSS_DIR will override everything else - you can
1681                   always set MOZNSS_DIR to force the use of this
1682                   directory
1683                   If using MOZNSS, specify the location of the moznss db dir
1684                   in the cacertdir directive of the OpenLDAP configuration.
1685                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1686                   find a security dir to use based on the current
1687                   settings
1688                 */
1689                 nn = 0;
1690                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1691                 securitydirs[nn++] = lt->lt_cacertdir;
1692                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1693                 for ( ii = 0; !done && ( ii < nn ); ++ii ) {
1694                         char *realcertdir = NULL;
1695                         const char *defprefix = "";
1696                         char *prefix = (char *)defprefix;
1697                         const char *securitydir = securitydirs[ii];
1698                         if ( NULL == securitydir ) {
1699                                 continue;
1700                         }
1701
1702                         tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
1703
1704                         /* initialize only moddb; certdb will be initialized explicitly */
1705 #ifdef HAVE_NSS_INITCONTEXT
1706 #ifdef INITCONTEXT_HACK
1707                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1708                                 rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1709                         } else {
1710                                 initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1711                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1712                         }
1713 #else
1714                         initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1715                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1716 #endif
1717                         rc = SECFailure;
1718
1719                         if ( initctx != NULL ) {
1720                                 certdb_slot = tlsm_init_open_certdb( ctx, realcertdir, prefix );
1721                                 if ( certdb_slot ) {
1722                                         rc = SECSuccess;
1723                                         ctx->tc_initctx = initctx;
1724                                         ctx->tc_certdb_slot = certdb_slot;
1725                                 } else {
1726                                         NSS_ShutdownContext( initctx );
1727                                         initctx = NULL;
1728                                 }
1729                         }
1730 #else
1731                         rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1732 #endif
1733
1734                         if ( rc != SECSuccess ) {
1735                                 errcode = PORT_GetError();
1736                                 if ( securitydirs[ii] != lt->lt_cacertdir) {
1737                                         Debug( LDAP_DEBUG_TRACE,
1738                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1739                                                    realcertdir, prefix, errcode );
1740                                 }
1741                         } else {
1742                                 /* success */
1743                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
1744                                            realcertdir, prefix, 0 );
1745                                 errcode = 0;
1746                                 done = 1;
1747                         }
1748                         if ( realcertdir != securitydir ) {
1749                                 PL_strfree( realcertdir );
1750                         }
1751                         if ( prefix != defprefix ) {
1752                                 PL_strfree( prefix );
1753                         }
1754                 }
1755
1756                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1757 #ifdef HAVE_NSS_INITCONTEXT
1758                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1759 #ifdef INITCONTEXT_HACK
1760                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1761                                 rc = NSS_NoDB_Init( NULL );
1762                         } else {
1763                                 initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1764                                                                                    &initParams, flags );
1765                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1766                         }
1767 #else
1768                         initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1769                                                                            &initParams, flags );
1770                         if ( initctx ) {
1771                                 ctx->tc_initctx = initctx;
1772                                 rc = SECSuccess;
1773                         } else {
1774                                 rc = SECFailure;
1775                         }
1776 #endif
1777 #else
1778                         rc = NSS_NoDB_Init( NULL );
1779 #endif
1780                         if ( rc != SECSuccess ) {
1781                                 errcode = PORT_GetError();
1782                                 Debug( LDAP_DEBUG_ANY,
1783                                            "TLS: could not initialize moznss - error %d:%s.\n",
1784                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1785                                 return -1;
1786                         }
1787                 }
1788
1789                 if ( errcode || lt->lt_cacertfile ) {
1790                         /* initialize the PEM module */
1791                         if ( tlsm_init_pem_module() ) {
1792                                 int pem_errcode = PORT_GetError();
1793                                 Debug( LDAP_DEBUG_ANY,
1794                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1795                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1796
1797                                 if ( errcode ) /* PEM is required */
1798                                         return -1;
1799
1800                         } else if ( !errcode ) {
1801                                 tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL );
1802                         }
1803                 }
1804
1805                 if ( errcode ) {
1806                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1807                                 /* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode 
1808                                    will be a value other than 1 - print an error message so that the
1809                                    user will know that failed too */
1810                                 if ( ( errcode != 1 ) && ( lt->lt_cacertdir ) ) {
1811                                         char *realcertdir = NULL;
1812                                         char *prefix = NULL;
1813                                         tlsm_get_certdb_prefix( lt->lt_cacertdir, &realcertdir, &prefix );
1814                                         Debug( LDAP_DEBUG_TRACE,
1815                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1816                                                    realcertdir, prefix ? prefix : "", errcode );
1817                                         if ( realcertdir != lt->lt_cacertdir ) {
1818                                                 PL_strfree( realcertdir );
1819                                         }
1820                                         PL_strfree( prefix );
1821                                 }
1822                                 return -1;
1823                         }
1824
1825                         ctx->tc_using_pem = PR_TRUE;
1826                 }
1827
1828                 NSS_SetDomesticPolicy();
1829
1830                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1831
1832                 /* register cleanup function */
1833                 if ( tlsm_register_nss_shutdown() ) {
1834                         errcode = PORT_GetError();
1835                         Debug( LDAP_DEBUG_ANY,
1836                                    "TLS: could not register NSS shutdown function: %d:%s\n",
1837                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1838                         return -1;
1839                 }
1840
1841                 if  ( ctx->tc_is_server ) {
1842                         /* 0 means use the defaults here */
1843                         SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1844                 }
1845
1846 #ifndef HAVE_NSS_INITCONTEXT
1847         }
1848 #endif /* HAVE_NSS_INITCONTEXT */
1849
1850         return 0;
1851 }
1852
1853 /*
1854  * Find and verify the certificate.
1855  * The key is loaded and stored in ctx->tc_private_key
1856  */
1857 static int
1858 tlsm_find_and_verify_cert_key( tlsm_ctx *ctx )
1859 {
1860         SECCertificateUsage certUsage;
1861         PRBool checkSig;
1862         SECStatus status;
1863         void *pin_arg;
1864
1865         if ( tlsm_ctx_load_private_key( ctx ) )
1866                 return -1;
1867
1868         pin_arg = SSL_RevealPinArg( ctx->tc_model );
1869         certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient;
1870         checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE;
1871
1872         status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg,
1873                                                            checkSig, certUsage, ctx->tc_warn_only, PR_TRUE );
1874
1875         return status == SECSuccess ? 0 : -1;
1876 }
1877
1878 static int
1879 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1880                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1881                                                    SECKEYPrivateKey **pRetKey )
1882 {
1883         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1884
1885         if ( pRetCert )
1886                 *pRetCert = CERT_DupCertificate( ctx->tc_certificate );
1887
1888         if ( pRetKey )
1889                 *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key );
1890
1891         return SECSuccess;
1892 }
1893
1894 /*
1895  * ctx must have a tc_model that is valid
1896 */
1897 static int
1898 tlsm_clientauth_init( tlsm_ctx *ctx )
1899 {
1900         SECStatus status = SECFailure;
1901         int rc;
1902         PRBool saveval;
1903
1904         saveval = ctx->tc_warn_only;
1905         ctx->tc_warn_only = PR_TRUE;
1906         rc = tlsm_find_and_verify_cert_key(ctx);
1907         ctx->tc_warn_only = saveval;
1908         if ( rc ) {
1909                 Debug( LDAP_DEBUG_ANY,
1910                            "TLS: error: unable to set up client certificate authentication for "
1911                            "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 );
1912                 return -1;
1913         }
1914
1915         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1916                                                                                 tlsm_get_client_auth_data,
1917                                                                                 (void *)ctx );
1918
1919         return ( status == SECSuccess ? 0 : -1 );
1920 }
1921
1922 /*
1923  * Tear down the TLS subsystem. Should only be called once.
1924  */
1925 static void
1926 tlsm_destroy( void )
1927 {
1928 #ifdef LDAP_R_COMPILE
1929         ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex );
1930         ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
1931         ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex );
1932 #endif
1933 }
1934
1935 static struct ldaptls *
1936 tlsm_copy_config ( const struct ldaptls *config )
1937 {
1938         struct ldaptls *copy;
1939
1940         assert( config );
1941
1942         copy = LDAP_MALLOC( sizeof( *copy ) );
1943         if ( !copy )
1944                 return NULL;
1945
1946         memset( copy, 0, sizeof( *copy ) );
1947
1948         if ( config->lt_certfile )
1949                 copy->lt_certfile = LDAP_STRDUP( config->lt_certfile );
1950         if ( config->lt_keyfile )
1951                 copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile );
1952         if ( config->lt_dhfile )
1953                 copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile );
1954         if ( config->lt_cacertfile )
1955                 copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile );
1956         if ( config->lt_cacertdir )
1957                 copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir );
1958         if ( config->lt_ciphersuite )
1959                 copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite );
1960         if ( config->lt_crlfile )
1961                 copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile );
1962         if ( config->lt_randfile )
1963                 copy->lt_randfile = LDAP_STRDUP( config->lt_randfile );
1964
1965         copy->lt_protocol_min = config->lt_protocol_min;
1966
1967         return copy;
1968 }
1969
1970 static void
1971 tlsm_free_config ( struct ldaptls *config )
1972 {
1973         assert( config );
1974
1975         if ( config->lt_certfile )
1976                 LDAP_FREE( config->lt_certfile );
1977         if ( config->lt_keyfile )
1978                 LDAP_FREE( config->lt_keyfile );
1979         if ( config->lt_dhfile )
1980                 LDAP_FREE( config->lt_dhfile );
1981         if ( config->lt_cacertfile )
1982                 LDAP_FREE( config->lt_cacertfile );
1983         if ( config->lt_cacertdir )
1984                 LDAP_FREE( config->lt_cacertdir );
1985         if ( config->lt_ciphersuite )
1986                 LDAP_FREE( config->lt_ciphersuite );
1987         if ( config->lt_crlfile )
1988                 LDAP_FREE( config->lt_crlfile );
1989         if ( config->lt_randfile )
1990                 LDAP_FREE( config->lt_randfile );
1991
1992         LDAP_FREE( config );
1993 }
1994
1995 static tls_ctx *
1996 tlsm_ctx_new ( struct ldapoptions *lo )
1997 {
1998         tlsm_ctx *ctx;
1999
2000         ctx = LDAP_MALLOC( sizeof (*ctx) );
2001         if ( ctx ) {
2002                 ctx->tc_refcnt = 1;
2003 #ifdef LDAP_R_COMPILE
2004                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
2005 #endif
2006                 LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex );
2007                 ctx->tc_unique = tlsm_ctx_count++;
2008                 LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex );
2009                 ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */
2010                 ctx->tc_certdb = NULL;
2011                 ctx->tc_certdb_slot = NULL;
2012                 ctx->tc_certificate = NULL;
2013                 ctx->tc_private_key = NULL;
2014                 ctx->tc_pin_file = NULL;
2015                 ctx->tc_model = NULL;
2016                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
2017                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
2018                 ctx->tc_verify_cert = PR_FALSE;
2019                 ctx->tc_using_pem = PR_FALSE;
2020 #ifdef HAVE_NSS_INITCONTEXT
2021                 ctx->tc_initctx = NULL;
2022 #endif /* HAVE_NSS_INITCONTEXT */
2023                 ctx->tc_pem_objs = NULL;
2024                 ctx->tc_n_pem_objs = 0;
2025                 ctx->tc_warn_only = PR_FALSE;
2026         }
2027         return (tls_ctx *)ctx;
2028 }
2029
2030 static void
2031 tlsm_ctx_ref( tls_ctx *ctx )
2032 {
2033         tlsm_ctx *c = (tlsm_ctx *)ctx;
2034         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2035         c->tc_refcnt++;
2036         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2037 }
2038
2039 static void
2040 tlsm_ctx_free ( tls_ctx *ctx )
2041 {
2042         tlsm_ctx *c = (tlsm_ctx *)ctx;
2043         int refcount;
2044
2045         if ( !c ) return;
2046
2047         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2048         refcount = --c->tc_refcnt;
2049         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2050         if ( refcount )
2051                 return;
2052
2053         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2054         if ( c->tc_model )
2055                 PR_Close( c->tc_model );
2056         if ( c->tc_certificate )
2057                 CERT_DestroyCertificate( c->tc_certificate );
2058         if ( c->tc_private_key )
2059                 SECKEY_DestroyPrivateKey( c->tc_private_key );
2060         c->tc_certdb = NULL; /* if not the default, may have to clean up */
2061         if ( c->tc_certdb_slot ) {
2062                 if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) {
2063                         PRErrorCode errcode = PR_GetError();
2064                         Debug( LDAP_DEBUG_ANY,
2065                                    "TLS: could not close certdb slot - error %d:%s.\n",
2066                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2067                 }
2068         }
2069         PL_strfree( c->tc_pin_file );
2070         c->tc_pin_file = NULL;
2071         tlsm_free_pem_objs( c );
2072 #ifdef HAVE_NSS_INITCONTEXT
2073         if ( c->tc_initctx ) {
2074                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2075                         PRErrorCode errcode = PR_GetError();
2076                         Debug( LDAP_DEBUG_ANY,
2077                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2078                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2079                 }
2080         }
2081         c->tc_initctx = NULL;
2082 #endif /* HAVE_NSS_INITCONTEXT */
2083         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2084 #ifdef LDAP_R_COMPILE
2085         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2086 #endif
2087
2088         if ( c->tc_config )
2089                 tlsm_free_config( c->tc_config );
2090
2091         LDAP_FREE( c );
2092 }
2093
2094 /*
2095  * initialize a new TLS context
2096  */
2097 static int
2098 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2099 {
2100         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2101         ctx->tc_config = tlsm_copy_config( lt );
2102         ctx->tc_is_server = is_server;
2103
2104         return 0;
2105 }
2106
2107 /* returns true if the given string looks like
2108    "tokenname" ":" "certnickname"
2109    This is true if there is a ':' colon character
2110    in the string and the colon is not the first
2111    or the last character in the string
2112 */
2113 static int
2114 tlsm_is_tokenname_certnick( const char *certfile )
2115 {
2116         if ( certfile ) {
2117                 const char *ptr = PL_strchr( certfile, ':' );
2118                 return ptr && (ptr != certfile) && (*(ptr+1));
2119         }
2120         return 0;
2121 }
2122
2123 static int
2124 tlsm_deferred_ctx_init( void *arg )
2125 {
2126         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2127         PRBool sslv2 = PR_FALSE;
2128         PRBool sslv3 = PR_TRUE;
2129         PRBool tlsv1 = PR_TRUE;
2130         PRBool request_cert = PR_FALSE;
2131         PRInt32 require_cert = PR_FALSE;
2132         PRFileDesc *fd;
2133         struct ldaptls *lt;
2134
2135         if ( tlsm_deferred_init( ctx ) ) {
2136             Debug( LDAP_DEBUG_ANY,
2137                            "TLS: could not perform TLS system initialization.\n",
2138                            0, 0, 0 );
2139             return -1;
2140         }
2141
2142         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2143
2144         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2145         if ( fd ) {
2146                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2147         }
2148
2149         if ( !ctx->tc_model ) {
2150                 PRErrorCode err = PR_GetError();
2151                 Debug( LDAP_DEBUG_ANY,
2152                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2153                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2154
2155                 if ( fd ) {
2156                         PR_Close( fd );
2157                 }
2158                 return -1;
2159         }
2160
2161         if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) {
2162                 Debug( LDAP_DEBUG_ANY,
2163                                 "TLS: could not set pin prompt argument\n", 0, 0, 0);
2164                 return -1;
2165         }
2166
2167         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2168                 Debug( LDAP_DEBUG_ANY,
2169                        "TLS: could not set secure mode on.\n",
2170                        0, 0, 0 );
2171                 return -1;
2172         }
2173
2174         lt = ctx->tc_config;
2175
2176         /* default is sslv3 and tlsv1 */
2177         if ( lt->lt_protocol_min ) {
2178                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2179                         sslv3 = PR_FALSE;
2180                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2181                         sslv2 = PR_TRUE;
2182                         Debug( LDAP_DEBUG_ANY,
2183                                "TLS: warning: minimum TLS protocol level set to "
2184                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2185                 }
2186         }
2187         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2188                 Debug( LDAP_DEBUG_ANY,
2189                        "TLS: could not set SSLv2 mode on.\n",
2190                        0, 0, 0 );
2191                 return -1;
2192         }
2193         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2194                 Debug( LDAP_DEBUG_ANY,
2195                        "TLS: could not set SSLv3 mode on.\n",
2196                        0, 0, 0 );
2197                 return -1;
2198         }
2199         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2200                 Debug( LDAP_DEBUG_ANY,
2201                        "TLS: could not set TLSv1 mode on.\n",
2202                        0, 0, 0 );
2203                 return -1;
2204         }
2205
2206         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2207                 Debug( LDAP_DEBUG_ANY,
2208                        "TLS: could not set handshake as client.\n",
2209                        0, 0, 0 );
2210                 return -1;
2211         }
2212         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2213                 Debug( LDAP_DEBUG_ANY,
2214                        "TLS: could not set handshake as server.\n",
2215                        0, 0, 0 );
2216                 return -1;
2217         }
2218
2219         if ( lt->lt_ciphersuite ) {
2220                 if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) {
2221                         Debug( LDAP_DEBUG_ANY,
2222                                "TLS: could not set cipher list %s.\n",
2223                                lt->lt_ciphersuite, 0, 0 );
2224                         return -1;
2225                 }
2226         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2227                 Debug( LDAP_DEBUG_ANY,
2228                        "TLS: could not set cipher list DEFAULT.\n",
2229                        0, 0, 0 );
2230                 return -1;
2231         }
2232
2233         if ( !ctx->tc_require_cert ) {
2234                 ctx->tc_verify_cert = PR_FALSE;
2235         } else if ( !ctx->tc_is_server ) {
2236                 request_cert = PR_TRUE;
2237                 require_cert = SSL_REQUIRE_NO_ERROR;
2238                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2239                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2240                         require_cert = SSL_REQUIRE_ALWAYS;
2241                 }
2242                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2243                         ctx->tc_verify_cert = PR_TRUE;
2244         } else { /* server */
2245                 /* server does not request certs by default */
2246                 /* if allow - client may send cert, server will ignore if errors */
2247                 /* if try - client may send cert, server will error if bad cert */
2248                 /* if hard or demand - client must send cert, server will error if bad cert */
2249                 request_cert = PR_TRUE;
2250                 require_cert = SSL_REQUIRE_NO_ERROR;
2251                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2252                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2253                         require_cert = SSL_REQUIRE_ALWAYS;
2254                 }
2255                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2256                         ctx->tc_verify_cert = PR_TRUE;
2257                 } else {
2258                         ctx->tc_warn_only = PR_TRUE;
2259                 }
2260         }
2261
2262         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2263                 Debug( LDAP_DEBUG_ANY,
2264                        "TLS: could not set request certificate mode.\n",
2265                        0, 0, 0 );
2266                 return -1;
2267         }
2268                 
2269         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2270                 Debug( LDAP_DEBUG_ANY,
2271                        "TLS: could not set require certificate mode.\n",
2272                        0, 0, 0 );
2273                 return -1;
2274         }
2275
2276         /* set up our cert and key, if any */
2277         if ( lt->lt_certfile ) {
2278                 /* if using the PEM module, load the PEM file specified by lt_certfile */
2279                 /* otherwise, assume this is the name of a cert already in the db */
2280                 if ( ctx->tc_using_pem ) {
2281                         /* this sets ctx->tc_certificate to the correct value */
2282                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE );
2283                         if ( rc ) {
2284                                 return rc;
2285                         }
2286                 } else {
2287                         char *tmp_certname;
2288
2289                         if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
2290                                 /* assume already in form tokenname:certnickname */
2291                                 tmp_certname = PL_strdup( lt->lt_certfile );
2292                         } else if ( ctx->tc_certdb_slot ) {
2293                                 tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile );
2294                         } else {
2295                                 tmp_certname = PR_smprintf( "%s", lt->lt_certfile );
2296                         }
2297
2298                         ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) );
2299                         PR_smprintf_free( tmp_certname );
2300
2301                         if ( !ctx->tc_certificate ) {
2302                                 PRErrorCode errcode = PR_GetError();
2303                                 Debug( LDAP_DEBUG_ANY,
2304                                            "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
2305                                            lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
2306                                 return -1;
2307                         }
2308                 }
2309         }
2310
2311         if ( lt->lt_keyfile ) {
2312                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2313                 /* otherwise, assume this is the pininfo for the key */
2314                 if ( ctx->tc_using_pem ) {
2315                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2316                         if ( rc ) {
2317                                 return rc;
2318                         }
2319                 } else {
2320                         PL_strfree( ctx->tc_pin_file );
2321                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2322                 }
2323         }
2324
2325         /* Set up callbacks for use by clients */
2326         if ( !ctx->tc_is_server ) {
2327                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2328                         PRErrorCode err = PR_GetError();
2329                         Debug( LDAP_DEBUG_ANY, 
2330                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2331                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2332                         return -1;
2333                 }
2334
2335                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2336                         PRErrorCode err = PR_GetError();
2337                         Debug( LDAP_DEBUG_ANY, 
2338                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2339                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2340                         return -1;
2341                 }
2342
2343                 /* 
2344                    since a cert has been specified, assume the client wants to do cert auth
2345                 */
2346                 if ( ctx->tc_certificate ) {
2347                         if ( tlsm_clientauth_init( ctx ) ) {
2348                                 Debug( LDAP_DEBUG_ANY, 
2349                                        "TLS: error: unable to set up client certificate authentication using '%s'\n",
2350                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2351                                 return -1;
2352                         }
2353                 }
2354         } else { /* set up secure server */
2355                 SSLKEAType certKEA;
2356                 SECStatus status;
2357
2358                 /* must have a certificate for the server to use */
2359                 if ( !ctx->tc_certificate ) {
2360                         Debug( LDAP_DEBUG_ANY, 
2361                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2362                                0, 0, 0 );
2363                         return -1;
2364                 }
2365
2366                 if ( tlsm_find_and_verify_cert_key( ctx ) ) {
2367                         Debug( LDAP_DEBUG_ANY, 
2368                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2369                                tlsm_ctx_subject_name(ctx), 0, 0 );
2370                         return -1;
2371                 }
2372
2373                 /* configure the socket to be a secure server socket */
2374                 certKEA = NSS_FindCertKEAType( ctx->tc_certificate );
2375                 status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA );
2376
2377                 if ( SECSuccess != status ) {
2378                         PRErrorCode err = PR_GetError();
2379                         Debug( LDAP_DEBUG_ANY, 
2380                                "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n",
2381                                tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2382                         return -1;
2383                 }
2384         }
2385
2386         /* Callback for authenticating certificate */
2387         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2388                                   ctx ) != SECSuccess ) {
2389                 PRErrorCode err = PR_GetError();
2390                 Debug( LDAP_DEBUG_ANY, 
2391                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2392                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2393                 return -1;
2394         }
2395
2396         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2397                 PRErrorCode err = PR_GetError();
2398                 Debug( LDAP_DEBUG_ANY, 
2399                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2400                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2401                 return -1;
2402         }
2403
2404         tlsm_free_config( ctx->tc_config );
2405         ctx->tc_config = NULL;
2406
2407         return 0;
2408 }
2409
2410 struct tls_data {
2411         tlsm_session            *session;
2412         Sockbuf_IO_Desc         *sbiod;
2413         /* there seems to be no portable way to determine if the
2414            sockbuf sd has been set to nonblocking mode - the
2415            call to ber_pvt_socket_set_nonblock() takes place
2416            before the tls socket is set up, so we cannot
2417            intercept that call either.
2418            On systems where fcntl is available, we can just
2419            F_GETFL and test for O_NONBLOCK.  On other systems,
2420            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2421            and just set this flag */
2422         PRBool              nonblock;
2423         /*
2424          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2425          * clients that send an SSLv2 client hello.  This message is not
2426          * tagged in any way, so NSS has no way to know if the incoming
2427          * message is a valid SSLv2 client hello or just some bogus data
2428          * (or cleartext LDAP).  We store the first byte read from the
2429          * client here.  The most common case will be a client sending
2430          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2431          * for example, if using ldapsearch -Z - if the starttls fails,
2432          * the client will fallback to plain cleartext LDAP.  So if we
2433          * see that the firstbyte is a valid LDAP tag, we can be
2434          * pretty sure this is happening.
2435          */
2436         ber_tag_t           firsttag;
2437         /*
2438          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2439          * when it is blocked, so we have to set a flag in the wrapped send
2440          * and recv calls that tells us what operation NSS was last blocked
2441          * on
2442          */
2443 #define TLSM_READ  1
2444 #define TLSM_WRITE 2
2445         int io_flag;
2446 };
2447
2448 static struct tls_data *
2449 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2450 {
2451         struct tls_data         *p;
2452         PRFileDesc *myfd;
2453
2454         if ( !fd ) {
2455                 return NULL;
2456         }
2457
2458         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2459
2460         if ( !myfd ) {
2461                 return NULL;
2462         }
2463
2464         p = (struct tls_data *)myfd->secret;
2465
2466         return p;
2467 }
2468
2469 static int
2470 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2471 {
2472         struct tls_data         *p;
2473
2474         if ( thebyte ) {
2475                 *thebyte = LBER_DEFAULT;
2476         }
2477
2478         p = tlsm_get_pvt_tls_data( fd );
2479         if ( p == NULL || p->sbiod == NULL ) {
2480                 return 0;
2481         }
2482
2483         if ( p->firsttag == LBER_SEQUENCE ) {
2484                 if ( thebyte ) {
2485                         *thebyte = p->firsttag;
2486                 }
2487                 return 1;
2488         }
2489
2490         return 0;
2491 }
2492
2493 static tls_session *
2494 tlsm_session_new ( tls_ctx * ctx, int is_server )
2495 {
2496         tlsm_ctx *c = (tlsm_ctx *)ctx;
2497         tlsm_session *session;
2498         PRFileDesc *fd;
2499         PRStatus status;
2500         int rc;
2501
2502         c->tc_is_server = is_server;
2503         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2504         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2505         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2506         if ( PR_SUCCESS != status ) {
2507                 PRErrorCode err = PR_GetError();
2508                 Debug( LDAP_DEBUG_ANY, 
2509                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2510                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2511                 return NULL;
2512         }
2513
2514         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2515         if ( !fd ) {
2516                 return NULL;
2517         }
2518
2519         session = SSL_ImportFD( c->tc_model, fd );
2520         if ( !session ) {
2521                 PR_DELETE( fd );
2522                 return NULL;
2523         }
2524
2525         rc = SSL_ResetHandshake( session, is_server );
2526         if ( rc ) {
2527                 PRErrorCode err = PR_GetError();
2528                 Debug( LDAP_DEBUG_TRACE, 
2529                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2530                            rc, err,
2531                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2532                 PR_DELETE( fd );
2533                 PR_Close( session );
2534                 session = NULL;
2535         }
2536
2537         return (tls_session *)session;
2538
2539
2540 static int
2541 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2542 {
2543         tlsm_session *s = (tlsm_session *)session;
2544         int rc;
2545         const char *op = is_accept ? "accept" : "connect";
2546
2547         if ( pem_module ) {
2548                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2549         }
2550         rc = SSL_ForceHandshake( s );
2551         if ( pem_module ) {
2552                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2553         }
2554         if ( rc ) {
2555                 PRErrorCode err = PR_GetError();
2556                 rc = -1;
2557                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2558                         ber_tag_t thetag = LBER_DEFAULT;
2559                         /* see if we are blocked because of a bogus packet */
2560                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2561                                 Debug( LDAP_DEBUG_ANY, 
2562                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2563                                            op, (unsigned int)thetag, 0 );
2564                                 /* reset error to something more descriptive */
2565                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2566                         }
2567                 } else {
2568                         Debug( LDAP_DEBUG_ANY, 
2569                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2570                                    op, errno, err );
2571                 }
2572         }
2573
2574         return rc;
2575 }
2576 static int
2577 tlsm_session_accept( tls_session *session )
2578 {
2579         return tlsm_session_accept_or_connect( session, 1 );
2580 }
2581
2582 static int
2583 tlsm_session_connect( LDAP *ld, tls_session *session )
2584 {
2585         return tlsm_session_accept_or_connect( session, 0 );
2586 }
2587
2588 static int
2589 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2590 {
2591         int prerror = PR_GetError();
2592
2593         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2594                 tlsm_session *s = (tlsm_session *)session;
2595                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2596
2597                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2598                         sb->sb_trans_needs_read = 1;
2599                         return 1;
2600                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2601                         sb->sb_trans_needs_write = 1;
2602                         return 1;
2603                 }
2604         }
2605
2606         return 0;
2607 }
2608
2609 static char *
2610 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2611 {
2612         int i;
2613         int prerror = PR_GetError();
2614
2615         i = PR_GetErrorTextLength();
2616         if ( i > len ) {
2617                 char *msg = LDAP_MALLOC( i+1 );
2618                 PR_GetErrorText( msg );
2619                 memcpy( buf, msg, len );
2620                 LDAP_FREE( msg );
2621         } else if ( i ) {
2622                 PR_GetErrorText( buf );
2623         } else if ( prerror ) {
2624                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2625                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2626         }
2627
2628         return ( i > 0 ) ? buf : NULL;
2629 }
2630
2631 static int
2632 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2633 {
2634         tlsm_session *s = (tlsm_session *)session;
2635         CERTCertificate *cert;
2636
2637         cert = SSL_LocalCertificate( s );
2638         if (!cert) return LDAP_INVALID_CREDENTIALS;
2639
2640         der_dn->bv_val = (char *)cert->derSubject.data;
2641         der_dn->bv_len = cert->derSubject.len;
2642         CERT_DestroyCertificate( cert );
2643         return 0;
2644 }
2645
2646 static int
2647 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2648 {
2649         tlsm_session *s = (tlsm_session *)session;
2650         CERTCertificate *cert;
2651
2652         cert = SSL_PeerCertificate( s );
2653         if (!cert) return LDAP_INVALID_CREDENTIALS;
2654         
2655         der_dn->bv_val = (char *)cert->derSubject.data;
2656         der_dn->bv_len = cert->derSubject.len;
2657         CERT_DestroyCertificate( cert );
2658         return 0;
2659 }
2660
2661 /* what kind of hostname were we given? */
2662 #define IS_DNS  0
2663 #define IS_IP4  1
2664 #define IS_IP6  2
2665
2666 static int
2667 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2668 {
2669         tlsm_session *s = (tlsm_session *)session;
2670         CERTCertificate *cert;
2671         const char *name, *domain = NULL, *ptr;
2672         int ret, ntype = IS_DNS, nlen, dlen;
2673 #ifdef LDAP_PF_INET6
2674         struct in6_addr addr;
2675 #else
2676         struct in_addr addr;
2677 #endif
2678         SECItem altname;
2679         SECStatus rv;
2680
2681         if( ldap_int_hostname &&
2682                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2683         {
2684                 name = ldap_int_hostname;
2685         } else {
2686                 name = name_in;
2687         }
2688         nlen = strlen( name );
2689
2690         cert = SSL_PeerCertificate( s );
2691         if (!cert) {
2692                 Debug( LDAP_DEBUG_ANY,
2693                         "TLS: unable to get peer certificate.\n",
2694                         0, 0, 0 );
2695                 /* if this was a fatal condition, things would have
2696                  * aborted long before now.
2697                  */
2698                 return LDAP_SUCCESS;
2699         }
2700
2701 #ifdef LDAP_PF_INET6
2702         if (inet_pton(AF_INET6, name, &addr)) {
2703                 ntype = IS_IP6;
2704         } else 
2705 #endif
2706         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2707                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2708         }
2709         if (ntype == IS_DNS ) {
2710                 domain = strchr( name, '.' );
2711                 if ( domain )
2712                         dlen = nlen - ( domain - name );
2713         }
2714
2715         ret = LDAP_LOCAL_ERROR;
2716
2717         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2718                 &altname );
2719         if ( rv == SECSuccess && altname.data ) {
2720                 PRArenaPool *arena;
2721                 CERTGeneralName *names, *cur;
2722
2723                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2724                 if ( !arena ) {
2725                         ret = LDAP_NO_MEMORY;
2726                         goto fail;
2727                 }
2728
2729                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2730                 if ( !cur )
2731                         goto altfail;
2732
2733                 do {
2734                         char *host;
2735                         int hlen;
2736
2737                         /* ignore empty */
2738                         if ( !cur->name.other.len ) continue;
2739
2740                         host = (char *)cur->name.other.data;
2741                         hlen = cur->name.other.len;
2742
2743                         if ( cur->type == certDNSName ) {
2744                                 if ( ntype != IS_DNS )  continue;
2745
2746                                 /* is this an exact match? */
2747                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2748                                         ret = LDAP_SUCCESS;
2749                                         break;
2750                                 }
2751
2752                                 /* is this a wildcard match? */
2753                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2754                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2755                                         ret = LDAP_SUCCESS;
2756                                         break;
2757                                 }
2758                         } else if ( cur->type == certIPAddress ) {
2759                                 if ( ntype == IS_DNS )  continue;
2760                                 
2761 #ifdef LDAP_PF_INET6
2762                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2763                                         continue;
2764                                 } else
2765 #endif
2766                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2767                                         continue;
2768                                 }
2769                                 if (!memcmp(host, &addr, hlen)) {
2770                                         ret = LDAP_SUCCESS;
2771                                         break;
2772                                 }
2773                         }
2774                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2775 altfail:
2776                 PORT_FreeArena( arena, PR_FALSE );
2777                 SECITEM_FreeItem( &altname, PR_FALSE );
2778         }
2779         /* no altnames matched, try the CN */
2780         if ( ret != LDAP_SUCCESS ) {
2781                 /* find the last CN */
2782                 CERTRDN *rdn, **rdns;
2783                 CERTAVA *lastava = NULL;
2784                 char buf[2048];
2785
2786                 buf[0] = '\0';
2787                 rdns = cert->subject.rdns;
2788                 while ( rdns && ( rdn = *rdns++ )) {
2789                         CERTAVA *ava, **avas = rdn->avas;
2790                         while ( avas && ( ava = *avas++ )) {
2791                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2792                                         lastava = ava;
2793                         }
2794                 }
2795                 if ( lastava ) {
2796                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2797                         if ( av ) {
2798                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2799                                         ret = LDAP_SUCCESS;
2800                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2801                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2802                                                 (char *)(av->data+1), dlen )) {
2803                                         ret = LDAP_SUCCESS;
2804                                 } else {
2805                                         int len = av->len;
2806                                         if ( len >= sizeof(buf) )
2807                                                 len = sizeof(buf)-1;
2808                                         memcpy( buf, av->data, len );
2809                                         buf[len] = '\0';
2810                                 }
2811                                 SECITEM_FreeItem( av, PR_TRUE );
2812                         }
2813                 }
2814                 if ( ret != LDAP_SUCCESS ) {
2815                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2816                                 "common name in certificate (%s).\n", 
2817                                 name, buf, 0 );
2818                         ret = LDAP_CONNECT_ERROR;
2819                         if ( ld->ld_error ) {
2820                                 LDAP_FREE( ld->ld_error );
2821                         }
2822                         ld->ld_error = LDAP_STRDUP(
2823                                 _("TLS: hostname does not match CN in peer certificate"));
2824                 }
2825         }
2826
2827 fail:
2828         CERT_DestroyCertificate( cert );
2829         return ret;
2830 }
2831
2832 static int
2833 tlsm_session_strength( tls_session *session )
2834 {
2835         tlsm_session *s = (tlsm_session *)session;
2836         int rc, keySize;
2837
2838         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2839                 NULL, NULL );
2840         return rc ? 0 : keySize;
2841 }
2842
2843 static int
2844 tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
2845 {
2846         /* Need upstream support https://bugzilla.mozilla.org/show_bug.cgi?id=563276 */
2847         return 0;
2848 }
2849
2850 /* Yet again, we're pasting in glue that MozNSS ought to provide itself. */
2851 static struct {
2852         const char *name;
2853         int num;
2854 } pvers[] = {
2855         { "SSLv2", SSL_LIBRARY_VERSION_2 },
2856         { "SSLv3", SSL_LIBRARY_VERSION_3_0 },
2857         { "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 },
2858         { "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 },
2859         { NULL, 0 }
2860 };
2861
2862 static const char *
2863 tlsm_session_version( tls_session *sess )
2864 {
2865         tlsm_session *s = (tlsm_session *)sess;
2866         SSLChannelInfo info;
2867         int rc;
2868         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2869         if ( rc == 0 ) {
2870                 int i;
2871                 for (i=0; pvers[i].name; i++)
2872                         if (pvers[i].num == info.protocolVersion)
2873                                 return pvers[i].name;
2874         }
2875         return "unknown";
2876 }
2877
2878 static const char *
2879 tlsm_session_cipher( tls_session *sess )
2880 {
2881         tlsm_session *s = (tlsm_session *)sess;
2882         SSLChannelInfo info;
2883         int rc;
2884         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2885         if ( rc == 0 ) {
2886                 SSLCipherSuiteInfo csinfo;
2887                 rc = SSL_GetCipherSuiteInfo( info.cipherSuite, &csinfo, sizeof( csinfo ));
2888                 if ( rc == 0 )
2889                         return csinfo.cipherSuiteName;
2890         }
2891         return "unknown";
2892 }
2893
2894 static int
2895 tlsm_session_peercert( tls_session *sess, struct berval *der )
2896 {
2897         tlsm_session *s = (tlsm_session *)sess;
2898         CERTCertificate *cert;
2899         cert = SSL_PeerCertificate( s );
2900         if (!cert)
2901                 return -1;
2902         der->bv_len = cert->derCert.len;
2903         der->bv_val = LDAP_MALLOC( der->bv_len );
2904         if (!der->bv_val)
2905                 return -1;
2906         memcpy( der->bv_val, cert->derCert.data, der->bv_len );
2907         return 0;
2908 }
2909
2910 /*
2911  * TLS support for LBER Sockbufs
2912  */
2913
2914 static PRStatus PR_CALLBACK
2915 tlsm_PR_Close(PRFileDesc *fd)
2916 {
2917         int rc = PR_SUCCESS;
2918
2919         /* we don't need to actually close anything here, just
2920            pop our io layer off the stack */
2921         fd->secret = NULL; /* must have been freed before calling PR_Close */
2922         if ( fd->lower ) {
2923                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2924                 /* if we are not the last layer, pass the close along */
2925                 if ( fd ) {
2926                         if ( fd->dtor ) {
2927                                 fd->dtor( fd );
2928                         }
2929                         rc = fd->methods->close( fd );
2930                 }
2931         } else {
2932                 /* we are the last layer - just call our dtor */
2933                 fd->dtor(fd);
2934         }
2935
2936         return rc;
2937 }
2938
2939 static PRStatus PR_CALLBACK
2940 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2941 {
2942         int rc = PR_SUCCESS;
2943
2944         if ( fd->lower ) {
2945                 rc = PR_Shutdown( fd->lower, how );
2946         }
2947
2948         return rc;
2949 }
2950
2951 static int PR_CALLBACK
2952 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2953          PRIntervalTime timeout)
2954 {
2955         struct tls_data         *p;
2956         int rc;
2957
2958         if ( buf == NULL || len <= 0 ) return 0;
2959
2960         p = tlsm_get_pvt_tls_data( fd );
2961
2962         if ( p == NULL || p->sbiod == NULL ) {
2963                 return 0;
2964         }
2965
2966         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2967         if (rc <= 0) {
2968                 tlsm_map_error( errno );
2969                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2970                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2971                 } else if ( errno ) { /* real error */
2972                         Debug( LDAP_DEBUG_TRACE, 
2973                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2974                                rc, errno, STRERROR(errno) );
2975                 }
2976         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
2977                 p->firsttag = (ber_tag_t)*((char *)buf);
2978         }
2979         p->io_flag = TLSM_READ;
2980
2981         return rc;
2982 }
2983
2984 static int PR_CALLBACK
2985 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2986          PRIntervalTime timeout)
2987 {
2988         struct tls_data         *p;
2989         int rc;
2990
2991         if ( buf == NULL || len <= 0 ) return 0;
2992
2993         p = tlsm_get_pvt_tls_data( fd );
2994
2995         if ( p == NULL || p->sbiod == NULL ) {
2996                 return 0;
2997         }
2998
2999         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
3000         if (rc <= 0) {
3001                 tlsm_map_error( errno );
3002                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
3003                         p->nonblock = PR_TRUE;
3004                 } else if ( errno ) { /* real error */
3005                         Debug( LDAP_DEBUG_TRACE, 
3006                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
3007                                rc, errno, STRERROR(errno) );
3008                 }
3009         }
3010         p->io_flag = TLSM_WRITE;
3011
3012         return rc;
3013 }
3014
3015 static int PR_CALLBACK
3016 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
3017 {
3018         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3019 }
3020
3021 static int PR_CALLBACK
3022 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
3023 {
3024         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3025 }
3026
3027 static PRStatus PR_CALLBACK
3028 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
3029 {
3030         struct tls_data         *p;
3031         ber_socklen_t len;
3032
3033         p = tlsm_get_pvt_tls_data( fd );
3034
3035         if ( p == NULL || p->sbiod == NULL ) {
3036                 return PR_FAILURE;
3037         }
3038         len = sizeof(PRNetAddr);
3039         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
3040 }
3041
3042 static PRStatus PR_CALLBACK
3043 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
3044 {
3045         struct tls_data         *p;
3046         p = tlsm_get_pvt_tls_data( fd );
3047
3048         if ( p == NULL || data == NULL ) {
3049                 return PR_FAILURE;
3050         }
3051
3052         /* only the nonblocking option is supported at this time
3053            MozNSS SSL code needs it */
3054         if ( data->option != PR_SockOpt_Nonblocking ) {
3055                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3056                 return PR_FAILURE;
3057         }
3058 #ifdef HAVE_FCNTL
3059         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
3060         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
3061 #else /* punt :P */
3062         data->value.non_blocking = p->nonblock;
3063 #endif
3064         return PR_SUCCESS;
3065 }
3066
3067 static PRStatus PR_CALLBACK
3068 tlsm_PR_prs_unimp()
3069 {
3070     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3071     return PR_FAILURE;
3072 }
3073
3074 static PRFileDesc * PR_CALLBACK
3075 tlsm_PR_pfd_unimp()
3076 {
3077     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3078     return NULL;
3079 }
3080
3081 static PRInt16 PR_CALLBACK
3082 tlsm_PR_i16_unimp()
3083 {
3084     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3085     return SECFailure;
3086 }
3087
3088 static PRInt32 PR_CALLBACK
3089 tlsm_PR_i32_unimp()
3090 {
3091     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3092     return SECFailure;
3093 }
3094
3095 static PRInt64 PR_CALLBACK
3096 tlsm_PR_i64_unimp()
3097 {
3098     PRInt64 res;
3099
3100     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3101     LL_I2L(res, -1L);
3102     return res;
3103 }
3104
3105 static const PRIOMethods tlsm_PR_methods = {
3106     PR_DESC_LAYERED,
3107     tlsm_PR_Close,                      /* close        */
3108     tlsm_PR_Read,                       /* read         */
3109     tlsm_PR_Write,                      /* write        */
3110     tlsm_PR_i32_unimp,          /* available    */
3111     tlsm_PR_i64_unimp,          /* available64  */
3112     tlsm_PR_prs_unimp,          /* fsync        */
3113     tlsm_PR_i32_unimp,          /* seek         */
3114     tlsm_PR_i64_unimp,          /* seek64       */
3115     tlsm_PR_prs_unimp,          /* fileInfo     */
3116     tlsm_PR_prs_unimp,          /* fileInfo64   */
3117     tlsm_PR_i32_unimp,          /* writev       */
3118     tlsm_PR_prs_unimp,          /* connect      */
3119     tlsm_PR_pfd_unimp,          /* accept       */
3120     tlsm_PR_prs_unimp,          /* bind         */
3121     tlsm_PR_prs_unimp,          /* listen       */
3122     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3123     tlsm_PR_Recv,                       /* recv         */
3124     tlsm_PR_Send,                       /* send         */
3125     tlsm_PR_i32_unimp,          /* recvfrom     */
3126     tlsm_PR_i32_unimp,          /* sendto       */
3127     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3128     tlsm_PR_i32_unimp,          /* acceptread   */
3129     tlsm_PR_i32_unimp,          /* transmitfile */
3130     tlsm_PR_prs_unimp,          /* getsockname  */
3131     tlsm_PR_GetPeerName,        /* getpeername  */
3132     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3133     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3134     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3135     tlsm_PR_i32_unimp,          /* setsocketoption   */
3136     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3137     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3138     tlsm_PR_i32_unimp,          /* reserved for future use */
3139     tlsm_PR_i32_unimp,          /* reserved for future use */
3140     tlsm_PR_i32_unimp,          /* reserved for future use */
3141     tlsm_PR_i32_unimp           /* reserved for future use */
3142 };
3143
3144 /*
3145  * Initialize TLS subsystem. Should be called only once.
3146  * See tlsm_deferred_init for the bulk of the init process
3147  */
3148 static int
3149 tlsm_init( void )
3150 {
3151         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3152
3153         PR_Init(0, 0, 0);
3154
3155         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3156
3157         /*
3158          * There are some applications that acquire a crypto context in the parent process
3159          * and expect that crypto context to work after a fork().  This does not work
3160          * with NSS using strict PKCS11 compliance mode.  We set this environment
3161          * variable here to tell the software encryption module/token to allow crypto
3162          * contexts to persist across a fork().  However, if you are using some other
3163          * module or encryption device that supports and expects full PKCS11 semantics,
3164          * the only recourse is to rewrite the application with atfork() handlers to save
3165          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3166          * context in the child.
3167          */
3168         if ( !nofork ) {
3169                 /* will leak one time */
3170                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3171                 PR_SetEnv( noforkenvvar );
3172         }
3173
3174         return 0;
3175 }
3176
3177 static int
3178 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3179 {
3180         struct tls_data         *p;
3181         tlsm_session    *session = arg;
3182         PRFileDesc *fd;
3183
3184         assert( sbiod != NULL );
3185
3186         p = LBER_MALLOC( sizeof( *p ) );
3187         if ( p == NULL ) {
3188                 return -1;
3189         }
3190
3191         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3192         if ( !fd ) {
3193                 LBER_FREE( p );
3194                 return -1;
3195         }
3196
3197         fd->secret = (PRFilePrivate *)p;
3198         p->session = session;
3199         p->sbiod = sbiod;
3200         p->firsttag = LBER_DEFAULT;
3201         sbiod->sbiod_pvt = p;
3202         return 0;
3203 }
3204
3205 static int
3206 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
3207 {
3208         struct tls_data         *p;
3209         
3210         assert( sbiod != NULL );
3211         assert( sbiod->sbiod_pvt != NULL );
3212
3213         p = (struct tls_data *)sbiod->sbiod_pvt;
3214         PR_Close( p->session );
3215         LBER_FREE( sbiod->sbiod_pvt );
3216         sbiod->sbiod_pvt = NULL;
3217         return 0;
3218 }
3219
3220 static int
3221 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3222 {
3223         struct tls_data         *p;
3224         
3225         assert( sbiod != NULL );
3226         assert( sbiod->sbiod_pvt != NULL );
3227
3228         p = (struct tls_data *)sbiod->sbiod_pvt;
3229         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3230         return 0;
3231 }
3232
3233 static int
3234 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3235 {
3236         struct tls_data         *p;
3237         
3238         assert( sbiod != NULL );
3239         assert( sbiod->sbiod_pvt != NULL );
3240
3241         p = (struct tls_data *)sbiod->sbiod_pvt;
3242         
3243         if ( opt == LBER_SB_OPT_GET_SSL ) {
3244                 *((tlsm_session **)arg) = p->session;
3245                 return 1;
3246                 
3247         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3248                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3249                         return 1;
3250                 }
3251                 
3252         }
3253         
3254         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3255 }
3256
3257 static ber_slen_t
3258 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3259 {
3260         struct tls_data         *p;
3261         ber_slen_t              ret;
3262         int                     err;
3263
3264         assert( sbiod != NULL );
3265         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3266
3267         p = (struct tls_data *)sbiod->sbiod_pvt;
3268
3269         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3270         if ( ret < 0 ) {
3271                 err = PR_GetError();
3272                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3273                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3274                         sock_errset(EWOULDBLOCK);
3275                 }
3276         } else {
3277                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3278         }
3279         return ret;
3280 }
3281
3282 static ber_slen_t
3283 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3284 {
3285         struct tls_data         *p;
3286         ber_slen_t              ret;
3287         int                     err;
3288
3289         assert( sbiod != NULL );
3290         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3291
3292         p = (struct tls_data *)sbiod->sbiod_pvt;
3293
3294         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3295         if ( ret < 0 ) {
3296                 err = PR_GetError();
3297                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3298                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3299                         sock_errset(EWOULDBLOCK);
3300                         ret = 0;
3301                 }
3302         } else {
3303                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3304         }
3305         return ret;
3306 }
3307
3308 static Sockbuf_IO tlsm_sbio =
3309 {
3310         tlsm_sb_setup,          /* sbi_setup */
3311         tlsm_sb_remove,         /* sbi_remove */
3312         tlsm_sb_ctrl,           /* sbi_ctrl */
3313         tlsm_sb_read,           /* sbi_read */
3314         tlsm_sb_write,          /* sbi_write */
3315         tlsm_sb_close           /* sbi_close */
3316 };
3317
3318 tls_impl ldap_int_tls_impl = {
3319         "MozNSS",
3320
3321         tlsm_init,
3322         tlsm_destroy,
3323
3324         tlsm_ctx_new,
3325         tlsm_ctx_ref,
3326         tlsm_ctx_free,
3327         tlsm_ctx_init,
3328
3329         tlsm_session_new,
3330         tlsm_session_connect,
3331         tlsm_session_accept,
3332         tlsm_session_upflags,
3333         tlsm_session_errmsg,
3334         tlsm_session_my_dn,
3335         tlsm_session_peer_dn,
3336         tlsm_session_chkhost,
3337         tlsm_session_strength,
3338         tlsm_session_unique,
3339         tlsm_session_version,
3340         tlsm_session_cipher,
3341         tlsm_session_peercert,
3342
3343         &tlsm_sbio,
3344
3345 #ifdef LDAP_R_COMPILE
3346         tlsm_thr_init,
3347 #else
3348         NULL,
3349 #endif
3350
3351         0
3352 };
3353
3354 #endif /* HAVE_MOZNSS */
3355 /*
3356   emacs settings
3357   Local Variables:
3358   indent-tabs-mode: t
3359   tab-width: 4
3360   End:
3361 */