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