]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
Happy new year (belated)
[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-2014 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         if ( c->tc_pin_file ) {
2070                 PL_strfree( c->tc_pin_file );
2071                 c->tc_pin_file = NULL;
2072         }
2073         tlsm_free_pem_objs( c );
2074 #ifdef HAVE_NSS_INITCONTEXT
2075         if ( c->tc_initctx ) {
2076                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2077                         PRErrorCode errcode = PR_GetError();
2078                         Debug( LDAP_DEBUG_ANY,
2079                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2080                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2081                 }
2082         }
2083         c->tc_initctx = NULL;
2084 #endif /* HAVE_NSS_INITCONTEXT */
2085         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2086 #ifdef LDAP_R_COMPILE
2087         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2088 #endif
2089
2090         if ( c->tc_config )
2091                 tlsm_free_config( c->tc_config );
2092
2093         LDAP_FREE( c );
2094 }
2095
2096 /*
2097  * initialize a new TLS context
2098  */
2099 static int
2100 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2101 {
2102         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2103         ctx->tc_config = tlsm_copy_config( lt );
2104         ctx->tc_is_server = is_server;
2105
2106         return 0;
2107 }
2108
2109 /* returns true if the given string looks like
2110    "tokenname" ":" "certnickname"
2111    This is true if there is a ':' colon character
2112    in the string and the colon is not the first
2113    or the last character in the string
2114 */
2115 static int
2116 tlsm_is_tokenname_certnick( const char *certfile )
2117 {
2118         if ( certfile ) {
2119                 const char *ptr = PL_strchr( certfile, ':' );
2120                 return ptr && (ptr != certfile) && (*(ptr+1));
2121         }
2122         return 0;
2123 }
2124
2125 static int
2126 tlsm_deferred_ctx_init( void *arg )
2127 {
2128         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2129         PRBool sslv2 = PR_FALSE;
2130         PRBool sslv3 = PR_TRUE;
2131         PRBool tlsv1 = PR_TRUE;
2132         PRBool request_cert = PR_FALSE;
2133         PRInt32 require_cert = PR_FALSE;
2134         PRFileDesc *fd;
2135         struct ldaptls *lt;
2136
2137         if ( tlsm_deferred_init( ctx ) ) {
2138             Debug( LDAP_DEBUG_ANY,
2139                            "TLS: could not perform TLS system initialization.\n",
2140                            0, 0, 0 );
2141             return -1;
2142         }
2143
2144         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2145
2146         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2147         if ( fd ) {
2148                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2149         }
2150
2151         if ( !ctx->tc_model ) {
2152                 PRErrorCode err = PR_GetError();
2153                 Debug( LDAP_DEBUG_ANY,
2154                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2155                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2156
2157                 if ( fd ) {
2158                         PR_Close( fd );
2159                 }
2160                 return -1;
2161         }
2162
2163         if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) {
2164                 Debug( LDAP_DEBUG_ANY,
2165                                 "TLS: could not set pin prompt argument\n", 0, 0, 0);
2166                 return -1;
2167         }
2168
2169         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2170                 Debug( LDAP_DEBUG_ANY,
2171                        "TLS: could not set secure mode on.\n",
2172                        0, 0, 0 );
2173                 return -1;
2174         }
2175
2176         lt = ctx->tc_config;
2177
2178         /* default is sslv3 and tlsv1 */
2179         if ( lt->lt_protocol_min ) {
2180                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2181                         sslv3 = PR_FALSE;
2182                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2183                         sslv2 = PR_TRUE;
2184                         Debug( LDAP_DEBUG_ANY,
2185                                "TLS: warning: minimum TLS protocol level set to "
2186                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2187                 }
2188         }
2189         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2190                 Debug( LDAP_DEBUG_ANY,
2191                        "TLS: could not set SSLv2 mode on.\n",
2192                        0, 0, 0 );
2193                 return -1;
2194         }
2195         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2196                 Debug( LDAP_DEBUG_ANY,
2197                        "TLS: could not set SSLv3 mode on.\n",
2198                        0, 0, 0 );
2199                 return -1;
2200         }
2201         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2202                 Debug( LDAP_DEBUG_ANY,
2203                        "TLS: could not set TLSv1 mode on.\n",
2204                        0, 0, 0 );
2205                 return -1;
2206         }
2207
2208         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2209                 Debug( LDAP_DEBUG_ANY,
2210                        "TLS: could not set handshake as client.\n",
2211                        0, 0, 0 );
2212                 return -1;
2213         }
2214         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2215                 Debug( LDAP_DEBUG_ANY,
2216                        "TLS: could not set handshake as server.\n",
2217                        0, 0, 0 );
2218                 return -1;
2219         }
2220
2221         if ( lt->lt_ciphersuite ) {
2222                 if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) {
2223                         Debug( LDAP_DEBUG_ANY,
2224                                "TLS: could not set cipher list %s.\n",
2225                                lt->lt_ciphersuite, 0, 0 );
2226                         return -1;
2227                 }
2228         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2229                 Debug( LDAP_DEBUG_ANY,
2230                        "TLS: could not set cipher list DEFAULT.\n",
2231                        0, 0, 0 );
2232                 return -1;
2233         }
2234
2235         if ( !ctx->tc_require_cert ) {
2236                 ctx->tc_verify_cert = PR_FALSE;
2237         } else if ( !ctx->tc_is_server ) {
2238                 request_cert = PR_TRUE;
2239                 require_cert = SSL_REQUIRE_NO_ERROR;
2240                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2241                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2242                         require_cert = SSL_REQUIRE_ALWAYS;
2243                 }
2244                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2245                         ctx->tc_verify_cert = PR_TRUE;
2246         } else { /* server */
2247                 /* server does not request certs by default */
2248                 /* if allow - client may send cert, server will ignore if errors */
2249                 /* if try - client may send cert, server will error if bad cert */
2250                 /* if hard or demand - client must send cert, server will error if bad cert */
2251                 request_cert = PR_TRUE;
2252                 require_cert = SSL_REQUIRE_NO_ERROR;
2253                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2254                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2255                         require_cert = SSL_REQUIRE_ALWAYS;
2256                 }
2257                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2258                         ctx->tc_verify_cert = PR_TRUE;
2259                 } else {
2260                         ctx->tc_warn_only = PR_TRUE;
2261                 }
2262         }
2263
2264         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2265                 Debug( LDAP_DEBUG_ANY,
2266                        "TLS: could not set request certificate mode.\n",
2267                        0, 0, 0 );
2268                 return -1;
2269         }
2270                 
2271         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2272                 Debug( LDAP_DEBUG_ANY,
2273                        "TLS: could not set require certificate mode.\n",
2274                        0, 0, 0 );
2275                 return -1;
2276         }
2277
2278         /* set up our cert and key, if any */
2279         if ( lt->lt_certfile ) {
2280                 /* if using the PEM module, load the PEM file specified by lt_certfile */
2281                 /* otherwise, assume this is the name of a cert already in the db */
2282                 if ( ctx->tc_using_pem ) {
2283                         /* this sets ctx->tc_certificate to the correct value */
2284                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE );
2285                         if ( rc ) {
2286                                 return rc;
2287                         }
2288                 } else {
2289                         char *tmp_certname;
2290
2291                         if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
2292                                 /* assume already in form tokenname:certnickname */
2293                                 tmp_certname = PL_strdup( lt->lt_certfile );
2294                         } else if ( ctx->tc_certdb_slot ) {
2295                                 tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile );
2296                         } else {
2297                                 tmp_certname = PR_smprintf( "%s", lt->lt_certfile );
2298                         }
2299
2300                         ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) );
2301                         PR_smprintf_free( tmp_certname );
2302
2303                         if ( !ctx->tc_certificate ) {
2304                                 PRErrorCode errcode = PR_GetError();
2305                                 Debug( LDAP_DEBUG_ANY,
2306                                            "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
2307                                            lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
2308                                 return -1;
2309                         }
2310                 }
2311         }
2312
2313         if ( lt->lt_keyfile ) {
2314                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2315                 /* otherwise, assume this is the pininfo for the key */
2316                 if ( ctx->tc_using_pem ) {
2317                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2318                         if ( rc ) {
2319                                 return rc;
2320                         }
2321                 } else {
2322                         if ( ctx->tc_pin_file )
2323                                 PL_strfree( ctx->tc_pin_file );
2324                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2325                 }
2326         }
2327
2328         /* Set up callbacks for use by clients */
2329         if ( !ctx->tc_is_server ) {
2330                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2331                         PRErrorCode err = PR_GetError();
2332                         Debug( LDAP_DEBUG_ANY, 
2333                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2334                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2335                         return -1;
2336                 }
2337
2338                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2339                         PRErrorCode err = PR_GetError();
2340                         Debug( LDAP_DEBUG_ANY, 
2341                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2342                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2343                         return -1;
2344                 }
2345
2346                 /* 
2347                    since a cert has been specified, assume the client wants to do cert auth
2348                 */
2349                 if ( ctx->tc_certificate ) {
2350                         if ( tlsm_clientauth_init( ctx ) ) {
2351                                 Debug( LDAP_DEBUG_ANY, 
2352                                        "TLS: error: unable to set up client certificate authentication using '%s'\n",
2353                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2354                                 return -1;
2355                         }
2356                 }
2357         } else { /* set up secure server */
2358                 SSLKEAType certKEA;
2359                 SECStatus status;
2360
2361                 /* must have a certificate for the server to use */
2362                 if ( !ctx->tc_certificate ) {
2363                         Debug( LDAP_DEBUG_ANY, 
2364                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2365                                0, 0, 0 );
2366                         return -1;
2367                 }
2368
2369                 if ( tlsm_find_and_verify_cert_key( ctx ) ) {
2370                         Debug( LDAP_DEBUG_ANY, 
2371                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2372                                tlsm_ctx_subject_name(ctx), 0, 0 );
2373                         return -1;
2374                 }
2375
2376                 /* configure the socket to be a secure server socket */
2377                 certKEA = NSS_FindCertKEAType( ctx->tc_certificate );
2378                 status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA );
2379
2380                 if ( SECSuccess != status ) {
2381                         PRErrorCode err = PR_GetError();
2382                         Debug( LDAP_DEBUG_ANY, 
2383                                "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n",
2384                                tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2385                         return -1;
2386                 }
2387         }
2388
2389         /* Callback for authenticating certificate */
2390         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2391                                   ctx ) != SECSuccess ) {
2392                 PRErrorCode err = PR_GetError();
2393                 Debug( LDAP_DEBUG_ANY, 
2394                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2395                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2396                 return -1;
2397         }
2398
2399         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2400                 PRErrorCode err = PR_GetError();
2401                 Debug( LDAP_DEBUG_ANY, 
2402                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2403                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2404                 return -1;
2405         }
2406
2407         tlsm_free_config( ctx->tc_config );
2408         ctx->tc_config = NULL;
2409
2410         return 0;
2411 }
2412
2413 struct tls_data {
2414         tlsm_session            *session;
2415         Sockbuf_IO_Desc         *sbiod;
2416         /* there seems to be no portable way to determine if the
2417            sockbuf sd has been set to nonblocking mode - the
2418            call to ber_pvt_socket_set_nonblock() takes place
2419            before the tls socket is set up, so we cannot
2420            intercept that call either.
2421            On systems where fcntl is available, we can just
2422            F_GETFL and test for O_NONBLOCK.  On other systems,
2423            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2424            and just set this flag */
2425         PRBool              nonblock;
2426         /*
2427          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2428          * clients that send an SSLv2 client hello.  This message is not
2429          * tagged in any way, so NSS has no way to know if the incoming
2430          * message is a valid SSLv2 client hello or just some bogus data
2431          * (or cleartext LDAP).  We store the first byte read from the
2432          * client here.  The most common case will be a client sending
2433          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2434          * for example, if using ldapsearch -Z - if the starttls fails,
2435          * the client will fallback to plain cleartext LDAP.  So if we
2436          * see that the firstbyte is a valid LDAP tag, we can be
2437          * pretty sure this is happening.
2438          */
2439         ber_tag_t           firsttag;
2440         /*
2441          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2442          * when it is blocked, so we have to set a flag in the wrapped send
2443          * and recv calls that tells us what operation NSS was last blocked
2444          * on
2445          */
2446 #define TLSM_READ  1
2447 #define TLSM_WRITE 2
2448         int io_flag;
2449 };
2450
2451 static struct tls_data *
2452 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2453 {
2454         struct tls_data         *p;
2455         PRFileDesc *myfd;
2456
2457         if ( !fd ) {
2458                 return NULL;
2459         }
2460
2461         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2462
2463         if ( !myfd ) {
2464                 return NULL;
2465         }
2466
2467         p = (struct tls_data *)myfd->secret;
2468
2469         return p;
2470 }
2471
2472 static int
2473 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2474 {
2475         struct tls_data         *p;
2476
2477         if ( thebyte ) {
2478                 *thebyte = LBER_DEFAULT;
2479         }
2480
2481         p = tlsm_get_pvt_tls_data( fd );
2482         if ( p == NULL || p->sbiod == NULL ) {
2483                 return 0;
2484         }
2485
2486         if ( p->firsttag == LBER_SEQUENCE ) {
2487                 if ( thebyte ) {
2488                         *thebyte = p->firsttag;
2489                 }
2490                 return 1;
2491         }
2492
2493         return 0;
2494 }
2495
2496 static tls_session *
2497 tlsm_session_new ( tls_ctx * ctx, int is_server )
2498 {
2499         tlsm_ctx *c = (tlsm_ctx *)ctx;
2500         tlsm_session *session;
2501         PRFileDesc *fd;
2502         PRStatus status;
2503         int rc;
2504
2505         c->tc_is_server = is_server;
2506         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2507         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2508         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2509         if ( PR_SUCCESS != status ) {
2510                 PRErrorCode err = PR_GetError();
2511                 Debug( LDAP_DEBUG_ANY, 
2512                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2513                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2514                 return NULL;
2515         }
2516
2517         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2518         if ( !fd ) {
2519                 return NULL;
2520         }
2521
2522         session = SSL_ImportFD( c->tc_model, fd );
2523         if ( !session ) {
2524                 PR_DELETE( fd );
2525                 return NULL;
2526         }
2527
2528         rc = SSL_ResetHandshake( session, is_server );
2529         if ( rc ) {
2530                 PRErrorCode err = PR_GetError();
2531                 Debug( LDAP_DEBUG_TRACE, 
2532                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2533                            rc, err,
2534                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2535                 PR_DELETE( fd );
2536                 PR_Close( session );
2537                 session = NULL;
2538         }
2539
2540         return (tls_session *)session;
2541
2542
2543 static int
2544 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2545 {
2546         tlsm_session *s = (tlsm_session *)session;
2547         int rc;
2548         const char *op = is_accept ? "accept" : "connect";
2549
2550         if ( pem_module ) {
2551                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2552         }
2553         rc = SSL_ForceHandshake( s );
2554         if ( pem_module ) {
2555                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2556         }
2557         if ( rc ) {
2558                 PRErrorCode err = PR_GetError();
2559                 rc = -1;
2560                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2561                         ber_tag_t thetag = LBER_DEFAULT;
2562                         /* see if we are blocked because of a bogus packet */
2563                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2564                                 Debug( LDAP_DEBUG_ANY, 
2565                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2566                                            op, (unsigned int)thetag, 0 );
2567                                 /* reset error to something more descriptive */
2568                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2569                         }
2570                 } else {
2571                         Debug( LDAP_DEBUG_ANY, 
2572                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2573                                    op, errno, err );
2574                 }
2575         }
2576
2577         return rc;
2578 }
2579 static int
2580 tlsm_session_accept( tls_session *session )
2581 {
2582         return tlsm_session_accept_or_connect( session, 1 );
2583 }
2584
2585 static int
2586 tlsm_session_connect( LDAP *ld, tls_session *session )
2587 {
2588         return tlsm_session_accept_or_connect( session, 0 );
2589 }
2590
2591 static int
2592 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2593 {
2594         int prerror = PR_GetError();
2595
2596         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2597                 tlsm_session *s = (tlsm_session *)session;
2598                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2599
2600                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2601                         sb->sb_trans_needs_read = 1;
2602                         return 1;
2603                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2604                         sb->sb_trans_needs_write = 1;
2605                         return 1;
2606                 }
2607         }
2608
2609         return 0;
2610 }
2611
2612 static char *
2613 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2614 {
2615         int i;
2616         int prerror = PR_GetError();
2617
2618         i = PR_GetErrorTextLength();
2619         if ( i > len ) {
2620                 char *msg = LDAP_MALLOC( i+1 );
2621                 PR_GetErrorText( msg );
2622                 memcpy( buf, msg, len );
2623                 LDAP_FREE( msg );
2624         } else if ( i ) {
2625                 PR_GetErrorText( buf );
2626         } else if ( prerror ) {
2627                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2628                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2629         }
2630
2631         return ( i > 0 ) ? buf : NULL;
2632 }
2633
2634 static int
2635 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2636 {
2637         tlsm_session *s = (tlsm_session *)session;
2638         CERTCertificate *cert;
2639
2640         cert = SSL_LocalCertificate( s );
2641         if (!cert) return LDAP_INVALID_CREDENTIALS;
2642
2643         der_dn->bv_val = (char *)cert->derSubject.data;
2644         der_dn->bv_len = cert->derSubject.len;
2645         CERT_DestroyCertificate( cert );
2646         return 0;
2647 }
2648
2649 static int
2650 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2651 {
2652         tlsm_session *s = (tlsm_session *)session;
2653         CERTCertificate *cert;
2654
2655         cert = SSL_PeerCertificate( s );
2656         if (!cert) return LDAP_INVALID_CREDENTIALS;
2657         
2658         der_dn->bv_val = (char *)cert->derSubject.data;
2659         der_dn->bv_len = cert->derSubject.len;
2660         CERT_DestroyCertificate( cert );
2661         return 0;
2662 }
2663
2664 /* what kind of hostname were we given? */
2665 #define IS_DNS  0
2666 #define IS_IP4  1
2667 #define IS_IP6  2
2668
2669 static int
2670 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2671 {
2672         tlsm_session *s = (tlsm_session *)session;
2673         CERTCertificate *cert;
2674         const char *name, *domain = NULL, *ptr;
2675         int ret, ntype = IS_DNS, nlen, dlen;
2676 #ifdef LDAP_PF_INET6
2677         struct in6_addr addr;
2678 #else
2679         struct in_addr addr;
2680 #endif
2681         SECItem altname;
2682         SECStatus rv;
2683
2684         if( ldap_int_hostname &&
2685                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2686         {
2687                 name = ldap_int_hostname;
2688         } else {
2689                 name = name_in;
2690         }
2691         nlen = strlen( name );
2692
2693         cert = SSL_PeerCertificate( s );
2694         if (!cert) {
2695                 Debug( LDAP_DEBUG_ANY,
2696                         "TLS: unable to get peer certificate.\n",
2697                         0, 0, 0 );
2698                 /* if this was a fatal condition, things would have
2699                  * aborted long before now.
2700                  */
2701                 return LDAP_SUCCESS;
2702         }
2703
2704 #ifdef LDAP_PF_INET6
2705         if (inet_pton(AF_INET6, name, &addr)) {
2706                 ntype = IS_IP6;
2707         } else 
2708 #endif
2709         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2710                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2711         }
2712         if (ntype == IS_DNS ) {
2713                 domain = strchr( name, '.' );
2714                 if ( domain )
2715                         dlen = nlen - ( domain - name );
2716         }
2717
2718         ret = LDAP_LOCAL_ERROR;
2719
2720         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2721                 &altname );
2722         if ( rv == SECSuccess && altname.data ) {
2723                 PRArenaPool *arena;
2724                 CERTGeneralName *names, *cur;
2725
2726                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2727                 if ( !arena ) {
2728                         ret = LDAP_NO_MEMORY;
2729                         goto fail;
2730                 }
2731
2732                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2733                 if ( !cur )
2734                         goto altfail;
2735
2736                 do {
2737                         char *host;
2738                         int hlen;
2739
2740                         /* ignore empty */
2741                         if ( !cur->name.other.len ) continue;
2742
2743                         host = (char *)cur->name.other.data;
2744                         hlen = cur->name.other.len;
2745
2746                         if ( cur->type == certDNSName ) {
2747                                 if ( ntype != IS_DNS )  continue;
2748
2749                                 /* is this an exact match? */
2750                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2751                                         ret = LDAP_SUCCESS;
2752                                         break;
2753                                 }
2754
2755                                 /* is this a wildcard match? */
2756                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2757                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2758                                         ret = LDAP_SUCCESS;
2759                                         break;
2760                                 }
2761                         } else if ( cur->type == certIPAddress ) {
2762                                 if ( ntype == IS_DNS )  continue;
2763                                 
2764 #ifdef LDAP_PF_INET6
2765                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2766                                         continue;
2767                                 } else
2768 #endif
2769                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2770                                         continue;
2771                                 }
2772                                 if (!memcmp(host, &addr, hlen)) {
2773                                         ret = LDAP_SUCCESS;
2774                                         break;
2775                                 }
2776                         }
2777                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2778 altfail:
2779                 PORT_FreeArena( arena, PR_FALSE );
2780                 SECITEM_FreeItem( &altname, PR_FALSE );
2781         }
2782         /* no altnames matched, try the CN */
2783         if ( ret != LDAP_SUCCESS ) {
2784                 /* find the last CN */
2785                 CERTRDN *rdn, **rdns;
2786                 CERTAVA *lastava = NULL;
2787                 char buf[2048];
2788
2789                 buf[0] = '\0';
2790                 rdns = cert->subject.rdns;
2791                 while ( rdns && ( rdn = *rdns++ )) {
2792                         CERTAVA *ava, **avas = rdn->avas;
2793                         while ( avas && ( ava = *avas++ )) {
2794                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2795                                         lastava = ava;
2796                         }
2797                 }
2798                 if ( lastava ) {
2799                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2800                         if ( av ) {
2801                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2802                                         ret = LDAP_SUCCESS;
2803                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2804                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2805                                                 (char *)(av->data+1), dlen )) {
2806                                         ret = LDAP_SUCCESS;
2807                                 } else {
2808                                         int len = av->len;
2809                                         if ( len >= sizeof(buf) )
2810                                                 len = sizeof(buf)-1;
2811                                         memcpy( buf, av->data, len );
2812                                         buf[len] = '\0';
2813                                 }
2814                                 SECITEM_FreeItem( av, PR_TRUE );
2815                         }
2816                 }
2817                 if ( ret != LDAP_SUCCESS ) {
2818                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2819                                 "common name in certificate (%s).\n", 
2820                                 name, buf, 0 );
2821                         ret = LDAP_CONNECT_ERROR;
2822                         if ( ld->ld_error ) {
2823                                 LDAP_FREE( ld->ld_error );
2824                         }
2825                         ld->ld_error = LDAP_STRDUP(
2826                                 _("TLS: hostname does not match CN in peer certificate"));
2827                 }
2828         }
2829
2830 fail:
2831         CERT_DestroyCertificate( cert );
2832         return ret;
2833 }
2834
2835 static int
2836 tlsm_session_strength( tls_session *session )
2837 {
2838         tlsm_session *s = (tlsm_session *)session;
2839         int rc, keySize;
2840
2841         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2842                 NULL, NULL );
2843         return rc ? 0 : keySize;
2844 }
2845
2846 static int
2847 tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
2848 {
2849         /* Need upstream support https://bugzilla.mozilla.org/show_bug.cgi?id=563276 */
2850         return 0;
2851 }
2852
2853 /* Yet again, we're pasting in glue that MozNSS ought to provide itself. */
2854 static struct {
2855         const char *name;
2856         int num;
2857 } pvers[] = {
2858         { "SSLv2", SSL_LIBRARY_VERSION_2 },
2859         { "SSLv3", SSL_LIBRARY_VERSION_3_0 },
2860         { "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 },
2861         { "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 },
2862         { NULL, 0 }
2863 };
2864
2865 static const char *
2866 tlsm_session_version( tls_session *sess )
2867 {
2868         tlsm_session *s = (tlsm_session *)sess;
2869         SSLChannelInfo info;
2870         int rc;
2871         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2872         if ( rc == 0 ) {
2873                 int i;
2874                 for (i=0; pvers[i].name; i++)
2875                         if (pvers[i].num == info.protocolVersion)
2876                                 return pvers[i].name;
2877         }
2878         return "unknown";
2879 }
2880
2881 static const char *
2882 tlsm_session_cipher( tls_session *sess )
2883 {
2884         tlsm_session *s = (tlsm_session *)sess;
2885         SSLChannelInfo info;
2886         int rc;
2887         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2888         if ( rc == 0 ) {
2889                 SSLCipherSuiteInfo csinfo;
2890                 rc = SSL_GetCipherSuiteInfo( info.cipherSuite, &csinfo, sizeof( csinfo ));
2891                 if ( rc == 0 )
2892                         return csinfo.cipherSuiteName;
2893         }
2894         return "unknown";
2895 }
2896
2897 static int
2898 tlsm_session_peercert( tls_session *sess, struct berval *der )
2899 {
2900         tlsm_session *s = (tlsm_session *)sess;
2901         CERTCertificate *cert;
2902         cert = SSL_PeerCertificate( s );
2903         if (!cert)
2904                 return -1;
2905         der->bv_len = cert->derCert.len;
2906         der->bv_val = LDAP_MALLOC( der->bv_len );
2907         if (!der->bv_val)
2908                 return -1;
2909         memcpy( der->bv_val, cert->derCert.data, der->bv_len );
2910         return 0;
2911 }
2912
2913 /*
2914  * TLS support for LBER Sockbufs
2915  */
2916
2917 static PRStatus PR_CALLBACK
2918 tlsm_PR_Close(PRFileDesc *fd)
2919 {
2920         int rc = PR_SUCCESS;
2921
2922         /* we don't need to actually close anything here, just
2923            pop our io layer off the stack */
2924         fd->secret = NULL; /* must have been freed before calling PR_Close */
2925         if ( fd->lower ) {
2926                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2927                 /* if we are not the last layer, pass the close along */
2928                 if ( fd ) {
2929                         if ( fd->dtor ) {
2930                                 fd->dtor( fd );
2931                         }
2932                         rc = fd->methods->close( fd );
2933                 }
2934         } else {
2935                 /* we are the last layer - just call our dtor */
2936                 fd->dtor(fd);
2937         }
2938
2939         return rc;
2940 }
2941
2942 static PRStatus PR_CALLBACK
2943 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2944 {
2945         int rc = PR_SUCCESS;
2946
2947         if ( fd->lower ) {
2948                 rc = PR_Shutdown( fd->lower, how );
2949         }
2950
2951         return rc;
2952 }
2953
2954 static int PR_CALLBACK
2955 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2956          PRIntervalTime timeout)
2957 {
2958         struct tls_data         *p;
2959         int rc;
2960
2961         if ( buf == NULL || len <= 0 ) return 0;
2962
2963         p = tlsm_get_pvt_tls_data( fd );
2964
2965         if ( p == NULL || p->sbiod == NULL ) {
2966                 return 0;
2967         }
2968
2969         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2970         if (rc <= 0) {
2971                 tlsm_map_error( errno );
2972                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2973                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2974                 } else if ( errno ) { /* real error */
2975                         Debug( LDAP_DEBUG_TRACE, 
2976                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2977                                rc, errno, STRERROR(errno) );
2978                 }
2979         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
2980                 p->firsttag = (ber_tag_t)*((char *)buf);
2981         }
2982         p->io_flag = TLSM_READ;
2983
2984         return rc;
2985 }
2986
2987 static int PR_CALLBACK
2988 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2989          PRIntervalTime timeout)
2990 {
2991         struct tls_data         *p;
2992         int rc;
2993
2994         if ( buf == NULL || len <= 0 ) return 0;
2995
2996         p = tlsm_get_pvt_tls_data( fd );
2997
2998         if ( p == NULL || p->sbiod == NULL ) {
2999                 return 0;
3000         }
3001
3002         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
3003         if (rc <= 0) {
3004                 tlsm_map_error( errno );
3005                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
3006                         p->nonblock = PR_TRUE;
3007                 } else if ( errno ) { /* real error */
3008                         Debug( LDAP_DEBUG_TRACE, 
3009                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
3010                                rc, errno, STRERROR(errno) );
3011                 }
3012         }
3013         p->io_flag = TLSM_WRITE;
3014
3015         return rc;
3016 }
3017
3018 static int PR_CALLBACK
3019 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
3020 {
3021         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3022 }
3023
3024 static int PR_CALLBACK
3025 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
3026 {
3027         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3028 }
3029
3030 static PRStatus PR_CALLBACK
3031 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
3032 {
3033         struct tls_data         *p;
3034         ber_socklen_t len;
3035
3036         p = tlsm_get_pvt_tls_data( fd );
3037
3038         if ( p == NULL || p->sbiod == NULL ) {
3039                 return PR_FAILURE;
3040         }
3041         len = sizeof(PRNetAddr);
3042         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
3043 }
3044
3045 static PRStatus PR_CALLBACK
3046 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
3047 {
3048         struct tls_data         *p;
3049         p = tlsm_get_pvt_tls_data( fd );
3050
3051         if ( p == NULL || data == NULL ) {
3052                 return PR_FAILURE;
3053         }
3054
3055         /* only the nonblocking option is supported at this time
3056            MozNSS SSL code needs it */
3057         if ( data->option != PR_SockOpt_Nonblocking ) {
3058                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3059                 return PR_FAILURE;
3060         }
3061 #ifdef HAVE_FCNTL
3062         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
3063         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
3064 #else /* punt :P */
3065         data->value.non_blocking = p->nonblock;
3066 #endif
3067         return PR_SUCCESS;
3068 }
3069
3070 static PRStatus PR_CALLBACK
3071 tlsm_PR_prs_unimp()
3072 {
3073     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3074     return PR_FAILURE;
3075 }
3076
3077 static PRFileDesc * PR_CALLBACK
3078 tlsm_PR_pfd_unimp()
3079 {
3080     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3081     return NULL;
3082 }
3083
3084 static PRInt16 PR_CALLBACK
3085 tlsm_PR_i16_unimp()
3086 {
3087     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3088     return SECFailure;
3089 }
3090
3091 static PRInt32 PR_CALLBACK
3092 tlsm_PR_i32_unimp()
3093 {
3094     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3095     return SECFailure;
3096 }
3097
3098 static PRInt64 PR_CALLBACK
3099 tlsm_PR_i64_unimp()
3100 {
3101     PRInt64 res;
3102
3103     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3104     LL_I2L(res, -1L);
3105     return res;
3106 }
3107
3108 static const PRIOMethods tlsm_PR_methods = {
3109     PR_DESC_LAYERED,
3110     tlsm_PR_Close,                      /* close        */
3111     tlsm_PR_Read,                       /* read         */
3112     tlsm_PR_Write,                      /* write        */
3113     tlsm_PR_i32_unimp,          /* available    */
3114     tlsm_PR_i64_unimp,          /* available64  */
3115     tlsm_PR_prs_unimp,          /* fsync        */
3116     tlsm_PR_i32_unimp,          /* seek         */
3117     tlsm_PR_i64_unimp,          /* seek64       */
3118     tlsm_PR_prs_unimp,          /* fileInfo     */
3119     tlsm_PR_prs_unimp,          /* fileInfo64   */
3120     tlsm_PR_i32_unimp,          /* writev       */
3121     tlsm_PR_prs_unimp,          /* connect      */
3122     tlsm_PR_pfd_unimp,          /* accept       */
3123     tlsm_PR_prs_unimp,          /* bind         */
3124     tlsm_PR_prs_unimp,          /* listen       */
3125     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3126     tlsm_PR_Recv,                       /* recv         */
3127     tlsm_PR_Send,                       /* send         */
3128     tlsm_PR_i32_unimp,          /* recvfrom     */
3129     tlsm_PR_i32_unimp,          /* sendto       */
3130     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3131     tlsm_PR_i32_unimp,          /* acceptread   */
3132     tlsm_PR_i32_unimp,          /* transmitfile */
3133     tlsm_PR_prs_unimp,          /* getsockname  */
3134     tlsm_PR_GetPeerName,        /* getpeername  */
3135     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3136     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3137     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3138     tlsm_PR_i32_unimp,          /* setsocketoption   */
3139     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3140     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3141     tlsm_PR_i32_unimp,          /* reserved for future use */
3142     tlsm_PR_i32_unimp,          /* reserved for future use */
3143     tlsm_PR_i32_unimp,          /* reserved for future use */
3144     tlsm_PR_i32_unimp           /* reserved for future use */
3145 };
3146
3147 /*
3148  * Initialize TLS subsystem. Should be called only once.
3149  * See tlsm_deferred_init for the bulk of the init process
3150  */
3151 static int
3152 tlsm_init( void )
3153 {
3154         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3155
3156         PR_Init(0, 0, 0);
3157
3158         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3159
3160         /*
3161          * There are some applications that acquire a crypto context in the parent process
3162          * and expect that crypto context to work after a fork().  This does not work
3163          * with NSS using strict PKCS11 compliance mode.  We set this environment
3164          * variable here to tell the software encryption module/token to allow crypto
3165          * contexts to persist across a fork().  However, if you are using some other
3166          * module or encryption device that supports and expects full PKCS11 semantics,
3167          * the only recourse is to rewrite the application with atfork() handlers to save
3168          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3169          * context in the child.
3170          */
3171         if ( !nofork ) {
3172                 /* will leak one time */
3173                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3174                 PR_SetEnv( noforkenvvar );
3175         }
3176
3177         return 0;
3178 }
3179
3180 static int
3181 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3182 {
3183         struct tls_data         *p;
3184         tlsm_session    *session = arg;
3185         PRFileDesc *fd;
3186
3187         assert( sbiod != NULL );
3188
3189         p = LBER_MALLOC( sizeof( *p ) );
3190         if ( p == NULL ) {
3191                 return -1;
3192         }
3193
3194         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3195         if ( !fd ) {
3196                 LBER_FREE( p );
3197                 return -1;
3198         }
3199
3200         fd->secret = (PRFilePrivate *)p;
3201         p->session = session;
3202         p->sbiod = sbiod;
3203         p->firsttag = LBER_DEFAULT;
3204         sbiod->sbiod_pvt = p;
3205         return 0;
3206 }
3207
3208 static int
3209 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
3210 {
3211         struct tls_data         *p;
3212         
3213         assert( sbiod != NULL );
3214         assert( sbiod->sbiod_pvt != NULL );
3215
3216         p = (struct tls_data *)sbiod->sbiod_pvt;
3217         PR_Close( p->session );
3218         LBER_FREE( sbiod->sbiod_pvt );
3219         sbiod->sbiod_pvt = NULL;
3220         return 0;
3221 }
3222
3223 static int
3224 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3225 {
3226         struct tls_data         *p;
3227         
3228         assert( sbiod != NULL );
3229         assert( sbiod->sbiod_pvt != NULL );
3230
3231         p = (struct tls_data *)sbiod->sbiod_pvt;
3232         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3233         return 0;
3234 }
3235
3236 static int
3237 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3238 {
3239         struct tls_data         *p;
3240         
3241         assert( sbiod != NULL );
3242         assert( sbiod->sbiod_pvt != NULL );
3243
3244         p = (struct tls_data *)sbiod->sbiod_pvt;
3245         
3246         if ( opt == LBER_SB_OPT_GET_SSL ) {
3247                 *((tlsm_session **)arg) = p->session;
3248                 return 1;
3249                 
3250         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3251                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3252                         return 1;
3253                 }
3254                 
3255         }
3256         
3257         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3258 }
3259
3260 static ber_slen_t
3261 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3262 {
3263         struct tls_data         *p;
3264         ber_slen_t              ret;
3265         int                     err;
3266
3267         assert( sbiod != NULL );
3268         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3269
3270         p = (struct tls_data *)sbiod->sbiod_pvt;
3271
3272         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3273         if ( ret < 0 ) {
3274                 err = PR_GetError();
3275                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3276                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3277                         sock_errset(EWOULDBLOCK);
3278                 }
3279         } else {
3280                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3281         }
3282         return ret;
3283 }
3284
3285 static ber_slen_t
3286 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3287 {
3288         struct tls_data         *p;
3289         ber_slen_t              ret;
3290         int                     err;
3291
3292         assert( sbiod != NULL );
3293         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3294
3295         p = (struct tls_data *)sbiod->sbiod_pvt;
3296
3297         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3298         if ( ret < 0 ) {
3299                 err = PR_GetError();
3300                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3301                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3302                         sock_errset(EWOULDBLOCK);
3303                         ret = 0;
3304                 }
3305         } else {
3306                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3307         }
3308         return ret;
3309 }
3310
3311 static Sockbuf_IO tlsm_sbio =
3312 {
3313         tlsm_sb_setup,          /* sbi_setup */
3314         tlsm_sb_remove,         /* sbi_remove */
3315         tlsm_sb_ctrl,           /* sbi_ctrl */
3316         tlsm_sb_read,           /* sbi_read */
3317         tlsm_sb_write,          /* sbi_write */
3318         tlsm_sb_close           /* sbi_close */
3319 };
3320
3321 tls_impl ldap_int_tls_impl = {
3322         "MozNSS",
3323
3324         tlsm_init,
3325         tlsm_destroy,
3326
3327         tlsm_ctx_new,
3328         tlsm_ctx_ref,
3329         tlsm_ctx_free,
3330         tlsm_ctx_init,
3331
3332         tlsm_session_new,
3333         tlsm_session_connect,
3334         tlsm_session_accept,
3335         tlsm_session_upflags,
3336         tlsm_session_errmsg,
3337         tlsm_session_my_dn,
3338         tlsm_session_peer_dn,
3339         tlsm_session_chkhost,
3340         tlsm_session_strength,
3341         tlsm_session_unique,
3342         tlsm_session_version,
3343         tlsm_session_cipher,
3344         tlsm_session_peercert,
3345
3346         &tlsm_sbio,
3347
3348 #ifdef LDAP_R_COMPILE
3349         tlsm_thr_init,
3350 #else
3351         NULL,
3352 #endif
3353
3354         0
3355 };
3356
3357 #endif /* HAVE_MOZNSS */
3358 /*
3359   emacs settings
3360   Local Variables:
3361   indent-tabs-mode: t
3362   tab-width: 4
3363   End:
3364 */