]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
ITS#7313 MozNSS: store certificate object instead of nickname in in ctx
[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-2012 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->tc_pin_file ) {
905                 pwdstr = tlsm_get_pin_from_file( token_name, ctx );
906         }
907 #endif /* RETRIEVE_PASSWORD_FROM_FILE */
908 #ifdef READ_PASSWORD_FROM_STDIN
909         if ( !pwdstr ) {
910                 int infd = PR_FileDesc2NativeHandle( PR_STDIN );
911                 int isTTY = isatty( infd );
912                 unsigned char phrase[200];
913                 /* Prompt for password */
914                 if ( isTTY ) {
915                         fprintf( stdout,
916                                  "Please enter pin, password, or pass phrase for security token '%s': ",
917                                  token_name ? token_name : DEFAULT_TOKEN_NAME );
918                         echoOff( infd );
919                 }
920                 fgets( (char*)phrase, sizeof(phrase), stdin );
921                 if ( isTTY ) {
922                         fprintf( stdout, "\n" );
923                         echoOn( infd );
924                 }
925                 /* stomp on newline */
926                 phrase[strlen((char*)phrase)-1] = 0;
927
928                 pwdstr = PL_strdup( (char*)phrase );
929         }
930
931 #endif /* READ_PASSWORD_FROM_STDIN */
932         return pwdstr;
933 }
934
935 /*
936  * PKCS11 devices (including the internal softokn cert/key database)
937  * may be protected by a pin or password or even pass phrase
938  * MozNSS needs a way for the user to provide that
939  */
940 static char *
941 tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg)
942 {
943         tlsm_ctx *ctx = (tlsm_ctx *)arg;
944
945         return tlsm_get_pin( slot, retry, ctx );
946 }
947
948 static char *
949 tlsm_ctx_subject_name(tlsm_ctx *ctx)
950 {
951         if (!ctx || !ctx->tc_certificate)
952                 return "(unknown)";
953
954         return ctx->tc_certificate->subjectName;
955 }
956
957 static SECStatus
958 tlsm_get_basic_constraint_extension( CERTCertificate *cert,
959                                                                          CERTBasicConstraints *cbcval )
960 {
961         SECItem encodedVal = { 0, NULL };
962         SECStatus rc;
963
964         rc = CERT_FindCertExtension( cert, SEC_OID_X509_BASIC_CONSTRAINTS,
965                                                                  &encodedVal);
966         if ( rc != SECSuccess ) {
967                 return rc;
968         }
969
970         rc = CERT_DecodeBasicConstraintValue( cbcval, &encodedVal );
971
972         /* free the raw extension data */
973         PORT_Free( encodedVal.data );
974
975         return rc;
976 }
977
978 static PRBool
979 tlsm_cert_is_self_issued( CERTCertificate *cert )
980 {
981         /* A cert is self-issued if its subject and issuer are equal and
982          * both are of non-zero length. 
983          */
984         PRBool is_self_issued = cert &&
985                 (PRBool)SECITEM_ItemsAreEqual( &cert->derIssuer, 
986                                                                            &cert->derSubject ) &&
987                 cert->derSubject.len > 0;
988         return is_self_issued;
989 }
990
991 static SECStatus
992 tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
993                                  PRBool checksig, SECCertificateUsage certUsage, int errorToIgnore )
994 {
995         CERTVerifyLog verifylog;
996         SECStatus ret = SECSuccess;
997         const char *name;
998         int debug_level = LDAP_DEBUG_ANY;
999
1000         if ( errorToIgnore == -1 ) {
1001                 debug_level = LDAP_DEBUG_TRACE;
1002         }
1003
1004         /* the log captures information about every cert in the chain, so we can tell
1005            which cert caused the problem and what the problem was */
1006         memset( &verifylog, 0, sizeof( verifylog ) );
1007         verifylog.arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
1008         if ( verifylog.arena == NULL ) {
1009                 Debug( LDAP_DEBUG_ANY,
1010                            "TLS certificate verification: Out of memory for certificate verification logger\n",
1011                            0, 0, 0 );
1012                 return SECFailure;
1013         }
1014         ret = CERT_VerifyCertificate( handle, cert, checksig, certUsage, PR_Now(), pinarg, &verifylog,
1015                                                                   NULL );
1016         if ( ( name = cert->subjectName ) == NULL ) {
1017                 name = cert->nickname;
1018         }
1019         if ( verifylog.head == NULL ) {
1020                 /* it is possible for CERT_VerifyCertificate return with an error with no logging */
1021                 if ( ret != SECSuccess ) {
1022                         PRErrorCode errcode = PR_GetError();
1023                         Debug( debug_level,
1024                                    "TLS: certificate [%s] is not valid - error %d:%s.\n",
1025                                    name ? name : "(unknown)",
1026                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1027                 }
1028         } else {
1029                 const char *name;
1030                 CERTVerifyLogNode *node;
1031
1032                 ret = SECSuccess; /* reset */
1033                 node = verifylog.head;
1034                 while ( node ) {
1035                         if ( ( name = node->cert->subjectName ) == NULL ) {
1036                                 name = node->cert->nickname;
1037                         }
1038                         if ( node->error ) {
1039                                 /* NSS does not like CA certs that have the basic constraints extension
1040                                    with the CA flag set to FALSE - openssl doesn't check if the cert
1041                                    is self issued */
1042                                 if ( ( node->error == SEC_ERROR_CA_CERT_INVALID ) &&
1043                                          tlsm_cert_is_self_issued( node->cert ) ) {
1044
1045                                         PRErrorCode orig_error = PR_GetError();
1046                                         PRInt32 orig_oserror = PR_GetOSError();
1047
1048                                         CERTBasicConstraints basicConstraint;
1049                                         SECStatus rv = tlsm_get_basic_constraint_extension( node->cert, &basicConstraint );
1050                                         if ( ( rv == SECSuccess ) && ( basicConstraint.isCA == PR_FALSE ) ) {
1051                                                 Debug( LDAP_DEBUG_TRACE,
1052                                                            "TLS: certificate [%s] is not correct because it is a CA cert and the "
1053                                                            "BasicConstraint CA flag is set to FALSE - allowing for now, but "
1054                                                            "please fix your certs if possible\n", name, 0, 0 );
1055                                         } else { /* does not have basicconstraint, or some other error */
1056                                                 ret = SECFailure;
1057                                                 Debug( debug_level,
1058                                                            "TLS: certificate [%s] is not valid - CA cert is not valid\n",
1059                                                            name, 0, 0 );
1060                                         }
1061
1062                                         PR_SetError(orig_error, orig_oserror);
1063
1064                                 } else if ( errorToIgnore && ( node->error == errorToIgnore ) ) {
1065                                         Debug( debug_level,
1066                                                    "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
1067                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1068                                 } else {
1069                                         ret = SECFailure;
1070                                         Debug( debug_level,
1071                                                    "TLS: certificate [%s] is not valid - error %ld:%s.\n",
1072                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1073                                 }
1074                         }
1075                         CERT_DestroyCertificate( node->cert );
1076                         node = node->next;
1077                 }
1078         }
1079
1080         PORT_FreeArena( verifylog.arena, PR_FALSE );
1081
1082         if ( ret == SECSuccess ) {
1083                 Debug( LDAP_DEBUG_TRACE,
1084                            "TLS: certificate [%s] is valid\n", name, 0, 0 );
1085         } else if ( errorToIgnore == -1 ) {
1086                 ret = SECSuccess;
1087         }
1088
1089         return ret;
1090 }
1091
1092 static SECStatus
1093 tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
1094                        PRBool checksig, PRBool isServer)
1095 {
1096         SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
1097         SECStatus ret = SECSuccess;
1098         CERTCertificate *peercert = SSL_PeerCertificate( fd );
1099         int errorToIgnore = 0;
1100         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1101
1102         if (ctx && ctx->tc_warn_only )
1103                 errorToIgnore = -1;
1104
1105         ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
1106                                                         SSL_RevealPinArg( fd ),
1107                                                         checksig, certUsage, errorToIgnore );
1108         CERT_DestroyCertificate( peercert );
1109
1110         return ret;
1111 }
1112
1113 static int
1114 tlsm_authenticate_to_slot( tlsm_ctx *ctx, PK11SlotInfo *slot )
1115 {
1116         int rc = -1;
1117
1118         if ( SECSuccess != PK11_Authenticate( slot, PR_FALSE, ctx ) ) {
1119                 char *token_name = PK11_GetTokenName( slot );
1120                 PRErrorCode errcode = PR_GetError();
1121                 Debug( LDAP_DEBUG_ANY,
1122                            "TLS: could not authenticate to the security token %s - error %d:%s.\n",
1123                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1124                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1125         } else {
1126                 rc = 0; /* success */
1127         }
1128
1129         return rc;
1130 }
1131
1132 static SECStatus
1133 tlsm_nss_shutdown_cb( void *appData, void *nssData )
1134 {
1135         SECStatus rc = SECSuccess;
1136
1137         SSL_ShutdownServerSessionIDCache();
1138
1139         if ( pem_module ) {
1140                 SECMOD_UnloadUserModule( pem_module );
1141                 SECMOD_DestroyModule( pem_module );
1142                 pem_module = NULL;
1143         }
1144         return rc;
1145 }
1146
1147 static PRCallOnceType tlsm_register_shutdown_callonce = {0,0};
1148 static PRStatus PR_CALLBACK
1149 tlsm_register_nss_shutdown_cb( void )
1150 {
1151         if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb,
1152                                                                                          NULL ) ) {
1153                 return PR_SUCCESS;
1154         }
1155         return PR_FAILURE;
1156 }
1157
1158 static PRStatus
1159 tlsm_register_nss_shutdown( void )
1160 {
1161         return PR_CallOnce( &tlsm_register_shutdown_callonce,
1162                                                 tlsm_register_nss_shutdown_cb );
1163 }
1164
1165 static int
1166 tlsm_init_pem_module( void )
1167 {
1168         int rc = 0;
1169         char *fullname = NULL;
1170         char *configstring = NULL;
1171
1172         if ( pem_module ) {
1173                 return rc;
1174         }
1175
1176         /* not loaded - load it */
1177         /* get the system dependent library name */
1178         fullname = PR_GetLibraryName( NULL, PEM_LIBRARY );
1179         /* Load our PKCS#11 module */
1180         configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname );
1181         PL_strfree( fullname );
1182
1183         pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
1184         PR_smprintf_free( configstring );
1185
1186         if ( !pem_module || !pem_module->loaded ) {
1187                 if ( pem_module ) {
1188                         SECMOD_DestroyModule( pem_module );
1189                         pem_module = NULL;
1190                 }
1191                 rc = -1;
1192         }
1193
1194         return rc;
1195 }
1196
1197 static void
1198 tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
1199 {
1200         int idx = ctx->tc_n_pem_objs;
1201         ctx->tc_n_pem_objs++;
1202         ctx->tc_pem_objs = (PK11GenericObject **)
1203                 PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
1204         ctx->tc_pem_objs[idx] = obj;                                                                                                              
1205 }
1206
1207 static void
1208 tlsm_free_pem_objs( tlsm_ctx *ctx )
1209 {
1210         /* free in reverse order of allocation */
1211         while ( ctx->tc_n_pem_objs-- ) {
1212                 PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
1213                 ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
1214         }
1215         PORT_Free(ctx->tc_pem_objs);
1216         ctx->tc_pem_objs = NULL;
1217         ctx->tc_n_pem_objs = 0;
1218 }
1219
1220 static int
1221 tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
1222 {
1223         PK11SlotInfo *slot;
1224         PK11GenericObject *cert;
1225         CK_ATTRIBUTE attrs[4];
1226         CK_BBOOL cktrue = CK_TRUE;
1227         CK_BBOOL ckfalse = CK_FALSE;
1228         CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
1229         char *slotname;
1230         PRFileInfo fi;
1231         PRStatus status;
1232         SECItem certDER = { 0, NULL, 0 };
1233
1234         memset( &fi, 0, sizeof(fi) );
1235         status = PR_GetFileInfo( filename, &fi );
1236         if ( PR_SUCCESS != status) {
1237                 PRErrorCode errcode = PR_GetError();
1238                 Debug( LDAP_DEBUG_ANY,
1239                            "TLS: could not read certificate file %s - error %d:%s.\n",
1240                            filename, errcode,
1241                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1242                 return -1;
1243         }
1244
1245         if ( fi.type != PR_FILE_FILE ) {
1246                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1247                 Debug( LDAP_DEBUG_ANY,
1248                            "TLS: error: the certificate file %s is not a file.\n",
1249                            filename, 0 ,0 );
1250                 return -1;
1251         }
1252
1253         slotname = isca ? TLSM_PEM_SLOT_CACERTS : TLSM_PEM_SLOT_CERTS;
1254         slot = PK11_FindSlotByName( slotname );
1255
1256         if ( !slot ) {
1257                 PRErrorCode errcode = PR_GetError();
1258                 Debug( LDAP_DEBUG_ANY,
1259                            "TLS: could not find the slot for the certificate '%s' - error %d:%s.\n",
1260                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1261                 return -1;
1262         }
1263
1264         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) );
1265         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
1266         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 );
1267         PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof(CK_BBOOL) );
1268
1269         cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ );
1270
1271         if ( !cert ) {
1272                 PRErrorCode errcode = PR_GetError();
1273                 Debug( LDAP_DEBUG_ANY,
1274                            "TLS: could not add the certificate '%s' - error %d:%s.\n",
1275                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1276                 PK11_FreeSlot( slot );
1277                 return -1;
1278         }
1279
1280         /* if not CA, we store the certificate in ctx->tc_certificate */
1281         if ( !isca ) {
1282                 if ( PK11_ReadRawAttribute( PK11_TypeGeneric, cert, CKA_VALUE, &certDER ) != SECSuccess ) {
1283                         PRErrorCode errcode = PR_GetError();
1284                         Debug( LDAP_DEBUG_ANY,
1285                                         "TLS: could not get DER of the '%s' certificate - error %d:%s.\n",
1286                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1287                         PK11_DestroyGenericObject( cert );
1288                         PK11_FreeSlot( slot );
1289                         return -1;
1290                 }
1291
1292                 ctx->tc_certificate = PK11_FindCertFromDERCertItem( slot, &certDER, NULL );
1293                 SECITEM_FreeItem( &certDER, PR_FALSE );
1294
1295                 if ( !ctx->tc_certificate ) {
1296                         PRErrorCode errcode = PR_GetError();
1297                         Debug( LDAP_DEBUG_ANY,
1298                                         "TLS: could not get certificate '%s' using DER - error %d:%s.\n",
1299                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1300                         PK11_DestroyGenericObject( cert );
1301                         PK11_FreeSlot( slot );
1302                         return -1;
1303                 }
1304         }
1305
1306         tlsm_add_pem_obj( ctx, cert );
1307
1308         PK11_FreeSlot( slot );
1309
1310         return 0;
1311 }
1312
1313 static int
1314 tlsm_ctx_load_private_key(tlsm_ctx *ctx)
1315 {
1316         if (!ctx->tc_certificate)
1317                 return -1;
1318
1319         if (ctx->tc_private_key)
1320                 return 0;
1321
1322         void *pin_arg = SSL_RevealPinArg(ctx->tc_model);
1323
1324         ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg);
1325         if (!ctx->tc_private_key) {
1326                 PRErrorCode errcode = PR_GetError();
1327                 Debug(LDAP_DEBUG_ANY,
1328                                 "TLS: cannot find private key for certificate '%s' (error %d: %s)",
1329                                 tlsm_ctx_subject_name(ctx), errcode,
1330                                 PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT));
1331                 return -1;
1332         }
1333
1334         return 0;
1335 }
1336
1337 static int
1338 tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
1339 {
1340         PK11SlotInfo * slot = NULL;
1341         PK11GenericObject *key;
1342         CK_ATTRIBUTE attrs[3];
1343         CK_BBOOL cktrue = CK_TRUE;
1344         CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
1345         int retcode = 0;
1346         PRFileInfo fi;
1347         PRStatus status;
1348
1349         memset( &fi, 0, sizeof(fi) );
1350         status = PR_GetFileInfo( filename, &fi );
1351         if ( PR_SUCCESS != status) {
1352                 PRErrorCode errcode = PR_GetError();
1353                 Debug( LDAP_DEBUG_ANY,
1354                            "TLS: could not read key file %s - error %d:%s.\n",
1355                            filename, errcode,
1356                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1357                 return -1;
1358         }
1359
1360         if ( fi.type != PR_FILE_FILE ) {
1361                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1362                 Debug( LDAP_DEBUG_ANY,
1363                            "TLS: error: the key file %s is not a file.\n",
1364                            filename, 0 ,0 );
1365                 return -1;
1366         }
1367
1368         slot = PK11_FindSlotByName( TLSM_PEM_SLOT_CERTS );
1369
1370         if ( !slot ) {
1371                 PRErrorCode errcode = PR_GetError();
1372                 Debug( LDAP_DEBUG_ANY,
1373                            "TLS: could not find the slot for the private key '%s' - error %d:%s.\n",
1374                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1375                 return -1;
1376         }
1377
1378         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) );
1379         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
1380         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 );
1381
1382         key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ );
1383
1384         if ( !key ) {
1385                 PRErrorCode errcode = PR_GetError();
1386                 Debug( LDAP_DEBUG_ANY,
1387                            "TLS: could not add the private key '%s' - error %d:%s.\n",
1388                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1389                 retcode = -1;
1390         } else {
1391                 tlsm_add_pem_obj( ctx, key );
1392                 retcode = 0;
1393
1394                 /* When adding an encrypted key the PKCS#11 will be set as removed */
1395                 /* This will force the token to be seen as re-inserted */
1396                 SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
1397                 PK11_IsPresent( slot );
1398         }
1399
1400         PK11_FreeSlot( slot );
1401
1402         return retcode;
1403 }
1404
1405 static int
1406 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
1407 {
1408         PRBool isca = PR_TRUE;
1409         PRStatus status = PR_SUCCESS;
1410         PRErrorCode errcode = PR_SUCCESS;
1411
1412         if ( !cacertfile && !cacertdir ) {
1413                 /* no checking - not good, but allowed */
1414                 return 0;
1415         }
1416
1417         if ( cacertfile ) {
1418                 int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca );
1419                 if ( rc ) {
1420                         errcode = PR_GetError();
1421                         Debug( LDAP_DEBUG_ANY,
1422                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1423                                    cacertfile, errcode,
1424                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1425                         /* failure with cacertfile is a hard failure even if cacertdir is
1426                            also specified and contains valid CA cert files */
1427                         status = PR_FAILURE;
1428                 } else {
1429                         Debug( LDAP_DEBUG_TRACE,
1430                                    "TLS: loaded CA certificate file %s.\n",
1431                                    cacertfile, 0, 0 );
1432                 }
1433         }
1434
1435         /* if cacertfile above failed, we will return failure, even
1436            if there is a valid CA cert in cacertdir - but we still
1437            process cacertdir in case the user has enabled trace level
1438            debugging so they can see the processing for cacertdir too */
1439         /* any cacertdir failures are "soft" failures - if the user specifies
1440            no cert checking, then we allow the tls/ssl to continue, no matter
1441            what was specified for cacertdir, or the contents of the directory
1442            - this is different behavior than that of cacertfile */
1443         if ( cacertdir ) {
1444                 PRFileInfo fi;
1445                 PRDir *dir;
1446                 PRDirEntry *entry;
1447                 PRStatus fistatus = PR_FAILURE;
1448
1449                 memset( &fi, 0, sizeof(fi) );
1450                 fistatus = PR_GetFileInfo( cacertdir, &fi );
1451                 if ( PR_SUCCESS != fistatus) {
1452                         errcode = PR_GetError();
1453                         Debug( LDAP_DEBUG_ANY,
1454                                    "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
1455                                    cacertdir, errcode,
1456                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1457                         goto done;
1458                 }
1459
1460                 if ( fi.type != PR_FILE_DIRECTORY ) {
1461                         Debug( LDAP_DEBUG_ANY,
1462                                    "TLS: error: the CA certificate directory %s is not a directory.\n",
1463                                    cacertdir, 0 ,0 );
1464                         goto done;
1465                 }
1466
1467                 dir = PR_OpenDir( cacertdir );
1468                 if ( NULL == dir ) {
1469                         errcode = PR_GetError();
1470                         Debug( LDAP_DEBUG_ANY,
1471                                    "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
1472                                    cacertdir, errcode,
1473                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1474                         goto done;
1475                 }
1476
1477                 do {
1478                         entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
1479                         if ( ( NULL != entry ) && ( NULL != entry->name ) ) {
1480                                 char *fullpath = NULL;
1481                                 char *ptr;
1482
1483                                 ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX );
1484                                 if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) {
1485                                         Debug( LDAP_DEBUG_TRACE,
1486                                                    "TLS: file %s does not end in [%s] - does not appear to be a CA certificate "
1487                                                    "directory file with a properly hashed file name - skipping.\n",
1488                                                    entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 );
1489                                         continue;
1490                                 }
1491                                 fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
1492                                 if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) {
1493                                         Debug( LDAP_DEBUG_TRACE,
1494                                                    "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
1495                                                    fullpath, cacertdir, 0 );
1496                                 } else {
1497                                         errcode = PR_GetError();
1498                                         Debug( LDAP_DEBUG_TRACE,
1499                                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1500                                                    fullpath, errcode,
1501                                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1502                                 }
1503                                 PR_smprintf_free( fullpath );
1504                         }
1505                 } while ( NULL != entry );
1506                 PR_CloseDir( dir );
1507         }
1508 done:
1509         if ( status != PR_SUCCESS ) {
1510                 return -1;
1511         }
1512
1513         return 0;
1514 }
1515
1516 /*
1517  * NSS supports having multiple cert/key databases in the same
1518  * directory, each one having a unique string prefix e.g.
1519  * slapd-01-cert8.db - the prefix here is "slapd-01-"
1520  * this function examines the given certdir - if it looks like
1521  * /path/to/directory/prefix it will return the
1522  * /path/to/directory part in realcertdir, and the prefix in prefix
1523  */
1524 static void
1525 tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
1526 {
1527         char sep = PR_GetDirectorySeparator();
1528         char *ptr = NULL;
1529         struct PRFileInfo prfi;
1530         PRStatus prc;
1531
1532         *realcertdir = (char *)certdir; /* default is the one passed in */
1533
1534         /* if certdir is not given, just return */
1535         if ( !certdir ) {
1536                 return;
1537         }
1538
1539         prc = PR_GetFileInfo( certdir, &prfi );
1540         /* if certdir exists (file or directory) then it cannot specify a prefix */
1541         if ( prc == PR_SUCCESS ) {
1542                 return;
1543         }
1544
1545         /* if certdir was given, and there is a '/' in certdir, see if there
1546            is anything after the last '/' - if so, assume it is the prefix */
1547         if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
1548                 *realcertdir = PL_strndup( certdir, ptr-certdir );
1549                 *prefix = PL_strdup( ptr+1 );
1550         }
1551
1552         return;
1553 }
1554
1555 /*
1556  * Currently mutiple MozNSS contexts share one certificate storage. When the
1557  * certdb is being opened, only new certificates are added to the storage.
1558  * When different databases are used, conflicting nicknames make the
1559  * certificate lookup by the nickname impossible. In addition a token
1560  * description might be prepended in certain conditions.
1561  *
1562  * In order to make the certificate lookup by nickname possible, we explicitly
1563  * open each database using SECMOD_OpenUserDB and assign it the token
1564  * description. The token description is generated using ctx->tc_unique value,
1565  * which is unique for each context.
1566  */
1567 static PK11SlotInfo *
1568 tlsm_init_open_certdb(tlsm_ctx *ctx, const char *dbdir, const char *prefix)
1569 {
1570         PK11SlotInfo *slot = NULL;
1571         char *token_desc = NULL;
1572         char *config = NULL;
1573
1574         token_desc = PR_smprintf(TLSM_CERTDB_DESC_FMT, ctx->tc_unique);
1575         config = PR_smprintf("configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly",
1576                                                                                 dbdir, token_desc, prefix, prefix);
1577         Debug(LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0);
1578
1579         slot = SECMOD_OpenUserDB(config);
1580         if (!slot) {
1581                 PRErrorCode errcode = PR_GetError();
1582                 Debug(LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode,
1583                                                         PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT));
1584         }
1585
1586         if (token_desc)
1587                 PR_smprintf_free(token_desc);
1588         if (config)
1589                 PR_smprintf_free(config);
1590
1591         return slot;
1592 }
1593
1594 /*
1595  * This is the part of the init we defer until we get the
1596  * actual security configuration information.  This is
1597  * only called once, protected by a PRCallOnce
1598  * NOTE: This must be done before the first call to SSL_ImportFD,
1599  * especially the setting of the policy
1600  * NOTE: This must be called after fork()
1601  */
1602 static int
1603 tlsm_deferred_init( void *arg )
1604 {
1605         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1606         struct ldaptls *lt = ctx->tc_config;
1607         const char *securitydirs[3];
1608         int ii;
1609         int nn;
1610         PRErrorCode errcode = 1;
1611 #ifdef HAVE_NSS_INITCONTEXT
1612         NSSInitParameters initParams;
1613         NSSInitContext *initctx = NULL;
1614         PK11SlotInfo *certdb_slot = NULL;
1615 #endif
1616         SECStatus rc;
1617         int done = 0;
1618
1619 #ifdef HAVE_SECMOD_RESTARTMODULES
1620         /* NSS enforces the pkcs11 requirement that modules should be unloaded after
1621            a fork() - since there is no portable way to determine if NSS has been
1622            already initialized in a parent process, we just call SECMOD_RestartModules
1623            with force == FALSE - if the module has been unloaded due to a fork, it will
1624            be reloaded, otherwise, it is a no-op */
1625         if ( SECFailure == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) {
1626                 errcode = PORT_GetError();
1627                 if ( errcode != SEC_ERROR_NOT_INITIALIZED ) {
1628                         Debug( LDAP_DEBUG_TRACE,
1629                                    "TLS: could not restart the security modules: %d:%s\n",
1630                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1631                 } else {
1632                         errcode = 1;
1633                 }
1634         }
1635 #endif
1636
1637 #ifdef HAVE_NSS_INITCONTEXT
1638         memset( &initParams, 0, sizeof( initParams ) );
1639         initParams.length = sizeof( initParams );
1640 #endif /* HAVE_NSS_INITCONTEXT */
1641
1642 #ifdef LDAP_R_COMPILE
1643         if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) {
1644                 return -1;
1645         }
1646 #endif /* LDAP_R_COMPILE */
1647
1648 #ifndef HAVE_NSS_INITCONTEXT
1649         if ( !NSS_IsInitialized() ) {
1650 #endif /* HAVE_NSS_INITCONTEXT */
1651                 /*
1652                   MOZNSS_DIR will override everything else - you can
1653                   always set MOZNSS_DIR to force the use of this
1654                   directory
1655                   If using MOZNSS, specify the location of the moznss db dir
1656                   in the cacertdir directive of the OpenLDAP configuration.
1657                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1658                   find a security dir to use based on the current
1659                   settings
1660                 */
1661                 nn = 0;
1662                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1663                 securitydirs[nn++] = lt->lt_cacertdir;
1664                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1665                 for ( ii = 0; !done && ( ii < nn ); ++ii ) {
1666                         char *realcertdir = NULL;
1667                         const char *defprefix = "";
1668                         char *prefix = (char *)defprefix;
1669                         const char *securitydir = securitydirs[ii];
1670                         if ( NULL == securitydir ) {
1671                                 continue;
1672                         }
1673
1674                         tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
1675                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1676
1677                         /* initialize only moddb; certdb will be initialized explicitly */
1678 #ifdef HAVE_NSS_INITCONTEXT
1679 #ifdef INITCONTEXT_HACK
1680                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1681                                 rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1682                         } else {
1683                                 initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1684                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1685                         }
1686 #else
1687                         initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1688                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1689 #endif
1690                         rc = SECFailure;
1691
1692                         if (initctx != NULL) {
1693                                 certdb_slot = tlsm_init_open_certdb(ctx, realcertdir, prefix);
1694                                 if (certdb_slot) {
1695                                         rc = SECSuccess;
1696                                         ctx->tc_initctx = initctx;
1697                                         ctx->tc_certdb_slot = certdb_slot;
1698                                 } else {
1699                                         NSS_ShutdownContext(initctx);
1700                                         initctx = NULL;
1701                                 }
1702                         }
1703 #else
1704                         rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1705 #endif
1706
1707                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1708
1709                         if ( rc != SECSuccess ) {
1710                                 errcode = PORT_GetError();
1711                                 if ( securitydirs[ii] != lt->lt_cacertdir) {
1712                                         Debug( LDAP_DEBUG_TRACE,
1713                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1714                                                    realcertdir, prefix, errcode );
1715                                 }
1716                         } else {
1717                                 /* success */
1718                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
1719                                            realcertdir, prefix, 0 );
1720                                 errcode = 0;
1721                                 done = 1;
1722                         }
1723                         if ( realcertdir != securitydir ) {
1724                                 PL_strfree( realcertdir );
1725                         }
1726                         if ( prefix != defprefix ) {
1727                                 PL_strfree( prefix );
1728                         }
1729                 }
1730
1731                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1732                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1733 #ifdef HAVE_NSS_INITCONTEXT
1734                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1735 #ifdef INITCONTEXT_HACK
1736                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1737                                 rc = NSS_NoDB_Init( NULL );
1738                         } else {
1739                                 initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1740                                                                                    &initParams, flags );
1741                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1742                         }
1743 #else
1744                         initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1745                                                                            &initParams, flags );
1746                         if (initctx) {
1747                                 ctx->tc_initctx = initctx;
1748                                 rc = SECSuccess;
1749                         } else {
1750                                 rc = SECFailure;
1751                         }
1752 #endif
1753 #else
1754                         rc = NSS_NoDB_Init( NULL );
1755 #endif
1756                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1757                         if ( rc != SECSuccess ) {
1758                                 errcode = PORT_GetError();
1759                                 Debug( LDAP_DEBUG_ANY,
1760                                            "TLS: could not initialize moznss - error %d:%s.\n",
1761                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1762                                 return -1;
1763                         }
1764                 }
1765
1766                 if ( errcode || lt->lt_cacertfile ) {
1767                         /* initialize the PEM module */
1768                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1769                         if ( tlsm_init_pem_module() ) {
1770                                 LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1771                                 int pem_errcode = PORT_GetError();
1772                                 Debug( LDAP_DEBUG_ANY,
1773                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1774                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1775
1776                                 if ( errcode ) /* PEM is required */
1777                                         return -1;
1778
1779                         } else if ( !errcode ) {
1780                                 tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL );
1781                         }
1782                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1783                 }
1784
1785                 if ( errcode ) {
1786                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1787                                 /* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode 
1788                                    will be a value other than 1 - print an error message so that the
1789                                    user will know that failed too */
1790                                 if ( ( errcode != 1 ) && ( lt->lt_cacertdir ) ) {
1791                                         char *realcertdir = NULL;
1792                                         char *prefix = NULL;
1793                                         tlsm_get_certdb_prefix( lt->lt_cacertdir, &realcertdir, &prefix );
1794                                         Debug( LDAP_DEBUG_TRACE,
1795                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1796                                                    realcertdir, prefix ? prefix : "", errcode );
1797                                         if ( realcertdir != lt->lt_cacertdir ) {
1798                                                 PL_strfree( realcertdir );
1799                                         }
1800                                         PL_strfree( prefix );
1801                                 }
1802                                 return -1;
1803                         }
1804
1805                         ctx->tc_using_pem = PR_TRUE;
1806                 }
1807
1808                 NSS_SetDomesticPolicy();
1809
1810                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1811
1812                 /* register cleanup function */
1813                 if ( tlsm_register_nss_shutdown() ) {
1814                         errcode = PORT_GetError();
1815                         Debug( LDAP_DEBUG_ANY,
1816                                    "TLS: could not register NSS shutdown function: %d:%s\n",
1817                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1818                         return -1;
1819                 }
1820
1821                 if  ( ctx->tc_is_server ) {
1822                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1823                         /* 0 means use the defaults here */
1824                         SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1825                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1826                 }
1827
1828 #ifndef HAVE_NSS_INITCONTEXT
1829         }
1830 #endif /* HAVE_NSS_INITCONTEXT */
1831
1832         return 0;
1833 }
1834
1835 /*
1836  * Find and verify the certificate.
1837  * The key is loaded and stored in ctx->tc_private_key
1838  */
1839 static int
1840 tlsm_find_and_verify_cert_key(tlsm_ctx *ctx)
1841 {
1842         SECCertificateUsage certUsage;
1843         PRBool checkSig;
1844         SECStatus status;
1845         int errorToIgnore;
1846         void *pin_arg;
1847
1848         if (tlsm_ctx_load_private_key(ctx))
1849                 return -1;
1850
1851         pin_arg = SSL_RevealPinArg(ctx->tc_model);
1852         certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient;
1853         checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE;
1854         if ( ctx->tc_warn_only )
1855                 errorToIgnore = -1;
1856         else
1857                 errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER; /* may not have a CA cert */
1858
1859         status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg,
1860                                                            checkSig, certUsage, errorToIgnore );
1861
1862         return status == SECSuccess ? 0 : -1;
1863 }
1864
1865 static int
1866 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1867                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1868                                                    SECKEYPrivateKey **pRetKey )
1869 {
1870         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1871
1872         if (pRetCert)
1873                 *pRetCert = CERT_DupCertificate(ctx->tc_certificate);
1874
1875         if (pRetKey)
1876                 *pRetKey = SECKEY_CopyPrivateKey(ctx->tc_private_key);
1877
1878         return SECSuccess;
1879 }
1880
1881 /*
1882  * ctx must have a tc_model that is valid
1883 */
1884 static int
1885 tlsm_clientauth_init( tlsm_ctx *ctx )
1886 {
1887         SECStatus status = SECFailure;
1888         int rc;
1889         PRBool saveval;
1890
1891         saveval = ctx->tc_warn_only;
1892         ctx->tc_warn_only = PR_TRUE;
1893         rc = tlsm_find_and_verify_cert_key(ctx);
1894         ctx->tc_warn_only = saveval;
1895         if ( rc ) {
1896                 Debug( LDAP_DEBUG_ANY,
1897                            "TLS: error: unable to set up client certificate authentication for "
1898                            "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 );
1899                 return -1;
1900         }
1901
1902         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1903                                                                                 tlsm_get_client_auth_data,
1904                                                                                 (void *)ctx );
1905
1906         return ( status == SECSuccess ? 0 : -1 );
1907 }
1908
1909 /*
1910  * Tear down the TLS subsystem. Should only be called once.
1911  */
1912 static void
1913 tlsm_destroy( void )
1914 {
1915 #ifdef LDAP_R_COMPILE
1916         ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex );
1917         ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
1918         ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex );
1919 #endif
1920 }
1921
1922 static struct ldaptls *
1923 tlsm_copy_config ( const struct ldaptls *config )
1924 {
1925         struct ldaptls *copy;
1926
1927         assert(config);
1928
1929         copy = LDAP_MALLOC(sizeof(*copy));
1930         if (!copy)
1931                 return NULL;
1932
1933         memset(copy, 0, sizeof(*copy));
1934
1935         if (config->lt_certfile)
1936                 copy->lt_certfile = LDAP_STRDUP(config->lt_certfile);
1937         if (config->lt_keyfile)
1938                 copy->lt_keyfile = LDAP_STRDUP(config->lt_keyfile);
1939         if (config->lt_dhfile)
1940                 copy->lt_dhfile = LDAP_STRDUP(config->lt_dhfile);
1941         if (config->lt_cacertfile)
1942                 copy->lt_cacertfile = LDAP_STRDUP(config->lt_cacertfile);
1943         if (config->lt_cacertdir)
1944                 copy->lt_cacertdir = LDAP_STRDUP(config->lt_cacertdir);
1945         if (config->lt_ciphersuite)
1946                 copy->lt_ciphersuite = LDAP_STRDUP(config->lt_ciphersuite);
1947         if (config->lt_crlfile)
1948                 copy->lt_crlfile = LDAP_STRDUP(config->lt_crlfile);
1949         if (config->lt_randfile)
1950                 copy->lt_randfile = LDAP_STRDUP(config->lt_randfile);
1951
1952         copy->lt_protocol_min = config->lt_protocol_min;
1953
1954         return copy;
1955 }
1956
1957 static void
1958 tlsm_free_config ( struct ldaptls *config )
1959 {
1960         assert(config);
1961
1962         if (config->lt_certfile)
1963                 LDAP_FREE(config->lt_certfile);
1964         if (config->lt_keyfile)
1965                 LDAP_FREE(config->lt_keyfile);
1966         if (config->lt_dhfile)
1967                 LDAP_FREE(config->lt_dhfile);
1968         if (config->lt_cacertfile)
1969                 LDAP_FREE(config->lt_cacertfile);
1970         if (config->lt_cacertdir)
1971                 LDAP_FREE(config->lt_cacertdir);
1972         if (config->lt_ciphersuite)
1973                 LDAP_FREE(config->lt_ciphersuite);
1974         if (config->lt_crlfile)
1975                 LDAP_FREE(config->lt_crlfile);
1976         if (config->lt_randfile)
1977                 LDAP_FREE(config->lt_randfile);
1978
1979         LDAP_FREE(config);
1980 }
1981
1982 static tls_ctx *
1983 tlsm_ctx_new ( struct ldapoptions *lo )
1984 {
1985         tlsm_ctx *ctx;
1986
1987         ctx = LDAP_MALLOC( sizeof (*ctx) );
1988         if ( ctx ) {
1989                 ctx->tc_refcnt = 1;
1990 #ifdef LDAP_R_COMPILE
1991                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
1992 #endif
1993                 LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex );
1994                 ctx->tc_unique = tlsm_ctx_count++;
1995                 LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex );
1996                 ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */
1997                 ctx->tc_certdb = NULL;
1998                 ctx->tc_certdb_slot = NULL;
1999                 ctx->tc_certificate = NULL;
2000                 ctx->tc_private_key = NULL;
2001                 ctx->tc_pin_file = NULL;
2002                 ctx->tc_model = NULL;
2003                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
2004                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
2005                 ctx->tc_verify_cert = PR_FALSE;
2006                 ctx->tc_using_pem = PR_FALSE;
2007 #ifdef HAVE_NSS_INITCONTEXT
2008                 ctx->tc_initctx = NULL;
2009 #endif /* HAVE_NSS_INITCONTEXT */
2010                 ctx->tc_pem_objs = NULL;
2011                 ctx->tc_n_pem_objs = 0;
2012                 ctx->tc_warn_only = PR_FALSE;
2013         }
2014         return (tls_ctx *)ctx;
2015 }
2016
2017 static void
2018 tlsm_ctx_ref( tls_ctx *ctx )
2019 {
2020         tlsm_ctx *c = (tlsm_ctx *)ctx;
2021         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2022         c->tc_refcnt++;
2023         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2024 }
2025
2026 static void
2027 tlsm_ctx_free ( tls_ctx *ctx )
2028 {
2029         tlsm_ctx *c = (tlsm_ctx *)ctx;
2030         int refcount;
2031
2032         if ( !c ) return;
2033
2034         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2035         refcount = --c->tc_refcnt;
2036         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2037         if ( refcount )
2038                 return;
2039         if ( c->tc_model )
2040                 PR_Close( c->tc_model );
2041         if (c->tc_certificate)
2042                 CERT_DestroyCertificate(c->tc_certificate);
2043         if (c->tc_private_key)
2044                 SECKEY_DestroyPrivateKey(c->tc_private_key);
2045         c->tc_certdb = NULL; /* if not the default, may have to clean up */
2046         if ( c->tc_certdb_slot ) {
2047                 if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) {
2048                         PRErrorCode errcode = PR_GetError();
2049                         Debug( LDAP_DEBUG_ANY,
2050                                    "TLS: could not close certdb slot - error %d:%s.\n",
2051                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2052                 }
2053         }
2054         PL_strfree( c->tc_pin_file );
2055         c->tc_pin_file = NULL;
2056         tlsm_free_pem_objs( c );
2057 #ifdef HAVE_NSS_INITCONTEXT
2058         if ( c->tc_initctx ) {
2059                 LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2060                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2061                         PRErrorCode errcode = PR_GetError();
2062                         Debug( LDAP_DEBUG_ANY,
2063                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2064                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2065                 }
2066                 LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2067         }
2068         c->tc_initctx = NULL;
2069 #endif /* HAVE_NSS_INITCONTEXT */
2070 #ifdef LDAP_R_COMPILE
2071         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2072 #endif
2073
2074         if ( c->tc_config )
2075                 tlsm_free_config( c->tc_config );
2076
2077         LDAP_FREE( c );
2078 }
2079
2080 /*
2081  * initialize a new TLS context
2082  */
2083 static int
2084 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2085 {
2086         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2087         ctx->tc_config = tlsm_copy_config(lt);
2088         ctx->tc_is_server = is_server;
2089
2090         return 0;
2091 }
2092
2093 static int
2094 tlsm_deferred_ctx_init( void *arg )
2095 {
2096         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2097         PRBool sslv2 = PR_FALSE;
2098         PRBool sslv3 = PR_TRUE;
2099         PRBool tlsv1 = PR_TRUE;
2100         PRBool request_cert = PR_FALSE;
2101         PRInt32 require_cert = PR_FALSE;
2102         PRFileDesc *fd;
2103         struct ldaptls *lt;
2104
2105         if ( tlsm_deferred_init( ctx ) ) {
2106             Debug( LDAP_DEBUG_ANY,
2107                            "TLS: could not perform TLS system initialization.\n",
2108                            0, 0, 0 );
2109             return -1;
2110         }
2111
2112         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2113
2114         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2115         if ( fd ) {
2116                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2117         }
2118
2119         if ( !ctx->tc_model ) {
2120                 PRErrorCode err = PR_GetError();
2121                 Debug( LDAP_DEBUG_ANY,
2122                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2123                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2124
2125                 if ( fd ) {
2126                         PR_Close( fd );
2127                 }
2128                 return -1;
2129         }
2130
2131         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2132                 Debug( LDAP_DEBUG_ANY,
2133                        "TLS: could not set secure mode on.\n",
2134                        0, 0, 0 );
2135                 return -1;
2136         }
2137
2138         lt = ctx->tc_config;
2139
2140         /* default is sslv3 and tlsv1 */
2141         if ( lt->lt_protocol_min ) {
2142                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2143                         sslv3 = PR_FALSE;
2144                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2145                         sslv2 = PR_TRUE;
2146                         Debug( LDAP_DEBUG_ANY,
2147                                "TLS: warning: minimum TLS protocol level set to "
2148                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2149                 }
2150         }
2151         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2152                 Debug( LDAP_DEBUG_ANY,
2153                        "TLS: could not set SSLv2 mode on.\n",
2154                        0, 0, 0 );
2155                 return -1;
2156         }
2157         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2158                 Debug( LDAP_DEBUG_ANY,
2159                        "TLS: could not set SSLv3 mode on.\n",
2160                        0, 0, 0 );
2161                 return -1;
2162         }
2163         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2164                 Debug( LDAP_DEBUG_ANY,
2165                        "TLS: could not set TLSv1 mode on.\n",
2166                        0, 0, 0 );
2167                 return -1;
2168         }
2169
2170         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2171                 Debug( LDAP_DEBUG_ANY,
2172                        "TLS: could not set handshake as client.\n",
2173                        0, 0, 0 );
2174                 return -1;
2175         }
2176         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2177                 Debug( LDAP_DEBUG_ANY,
2178                        "TLS: could not set handshake as server.\n",
2179                        0, 0, 0 );
2180                 return -1;
2181         }
2182
2183         if ( lt->lt_ciphersuite ) {
2184                 if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) {
2185                         Debug( LDAP_DEBUG_ANY,
2186                                "TLS: could not set cipher list %s.\n",
2187                                lt->lt_ciphersuite, 0, 0 );
2188                         return -1;
2189                 }
2190         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2191                 Debug( LDAP_DEBUG_ANY,
2192                        "TLS: could not set cipher list DEFAULT.\n",
2193                        0, 0, 0 );
2194                 return -1;
2195         }
2196
2197         if ( !ctx->tc_require_cert ) {
2198                 ctx->tc_verify_cert = PR_FALSE;
2199         } else if ( !ctx->tc_is_server ) {
2200                 request_cert = PR_TRUE;
2201                 require_cert = SSL_REQUIRE_NO_ERROR;
2202                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2203                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2204                         require_cert = SSL_REQUIRE_ALWAYS;
2205                 }
2206                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2207                         ctx->tc_verify_cert = PR_TRUE;
2208         } else { /* server */
2209                 /* server does not request certs by default */
2210                 /* if allow - client may send cert, server will ignore if errors */
2211                 /* if try - client may send cert, server will error if bad cert */
2212                 /* if hard or demand - client must send cert, server will error if bad cert */
2213                 request_cert = PR_TRUE;
2214                 require_cert = SSL_REQUIRE_NO_ERROR;
2215                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2216                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2217                         require_cert = SSL_REQUIRE_ALWAYS;
2218                 }
2219                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2220                         ctx->tc_verify_cert = PR_TRUE;
2221                 } else {
2222                         ctx->tc_warn_only = PR_TRUE;
2223                 }
2224         }
2225
2226         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2227                 Debug( LDAP_DEBUG_ANY,
2228                        "TLS: could not set request certificate mode.\n",
2229                        0, 0, 0 );
2230                 return -1;
2231         }
2232                 
2233         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2234                 Debug( LDAP_DEBUG_ANY,
2235                        "TLS: could not set require certificate mode.\n",
2236                        0, 0, 0 );
2237                 return -1;
2238         }
2239
2240         /* set up our cert and key, if any */
2241         if ( lt->lt_certfile ) {
2242                 /* if using the PEM module, load the PEM file specified by lt_certfile */
2243                 /* otherwise, assume this is the name of a cert already in the db */
2244                 if ( ctx->tc_using_pem ) {
2245                         /* this sets ctx->tc_certificate to the correct value */
2246                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE );
2247                         if ( rc ) {
2248                                 return rc;
2249                         }
2250                 } else {
2251                         char *tmp_certname;
2252
2253                         if (ctx->tc_certdb_slot) {
2254                                 tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile);
2255                         } else {
2256                                 tmp_certname = PR_smprintf("%s", lt->lt_certfile);
2257                         }
2258
2259                         ctx->tc_certificate = PK11_FindCertFromNickname(tmp_certname, SSL_RevealPinArg(ctx->tc_model));
2260                         PR_smprintf_free(tmp_certname);
2261
2262                         if (!ctx->tc_certificate) {
2263                                 PRErrorCode errcode = PR_GetError();
2264                                 Debug( LDAP_DEBUG_ANY,
2265                                            "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
2266                                            lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
2267                                 return -1;
2268                         }
2269                 }
2270         }
2271
2272         if ( lt->lt_keyfile ) {
2273                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2274                 /* otherwise, assume this is the pininfo for the key */
2275                 if ( ctx->tc_using_pem ) {
2276                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2277                         if ( rc ) {
2278                                 return rc;
2279                         }
2280                 } else {
2281                         PL_strfree( ctx->tc_pin_file );
2282                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2283                 }
2284         }
2285
2286         /* Set up callbacks for use by clients */
2287         if ( !ctx->tc_is_server ) {
2288                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2289                         PRErrorCode err = PR_GetError();
2290                         Debug( LDAP_DEBUG_ANY, 
2291                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2292                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2293                         return -1;
2294                 }
2295
2296                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2297                         PRErrorCode err = PR_GetError();
2298                         Debug( LDAP_DEBUG_ANY, 
2299                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2300                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2301                         return -1;
2302                 }
2303
2304                 /* 
2305                    since a cert has been specified, assume the client wants to do cert auth
2306                 */
2307                 if ( ctx->tc_certificate ) {
2308                         if ( tlsm_authenticate_to_slot( ctx, ctx->tc_certificate->slot ) ) {
2309                                 Debug( LDAP_DEBUG_ANY, 
2310                                        "TLS: error: unable to authenticate to the security device for certificate '%s'\n",
2311                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2312                                 return -1;
2313                         }
2314                         if ( tlsm_clientauth_init( ctx ) ) {
2315                                 Debug( LDAP_DEBUG_ANY, 
2316                                        "TLS: error: unable to set up client certificate authentication using '%s'\n",
2317                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2318                                 return -1;
2319                         }
2320                 }
2321         } else { /* set up secure server */
2322                 SSLKEAType certKEA;
2323                 SECStatus status;
2324
2325                 /* must have a certificate for the server to use */
2326                 if ( !ctx->tc_certificate ) {
2327                         Debug( LDAP_DEBUG_ANY, 
2328                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2329                                0, 0, 0 );
2330                         return -1;
2331                 }
2332
2333                 /* authenticate to the server's token - this will do nothing
2334                    if the key/cert db is not password protected */
2335                 if ( tlsm_authenticate_to_slot( ctx, ctx->tc_certificate->slot ) ) {
2336                         Debug( LDAP_DEBUG_ANY, 
2337                                    "TLS: error: unable to authenticate to the security device for certificate '%s'\n",
2338                                    tlsm_ctx_subject_name(ctx), 0, 0 );
2339                         return -1;
2340                 }
2341
2342                 if (tlsm_find_and_verify_cert_key(ctx)) {
2343                         Debug( LDAP_DEBUG_ANY, 
2344                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2345                                tlsm_ctx_subject_name(ctx), 0, 0 );
2346                         return -1;
2347                 }
2348
2349                 /* configure the socket to be a secure server socket */
2350                 certKEA = NSS_FindCertKEAType( ctx->tc_certificate );
2351                 status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA );
2352
2353                 if ( SECSuccess != status ) {
2354                         PRErrorCode err = PR_GetError();
2355                         Debug( LDAP_DEBUG_ANY, 
2356                                "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n",
2357                                tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2358                         return -1;
2359                 }
2360         }
2361
2362         /* Callback for authenticating certificate */
2363         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2364                                   ctx ) != SECSuccess ) {
2365                 PRErrorCode err = PR_GetError();
2366                 Debug( LDAP_DEBUG_ANY, 
2367                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2368                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2369                 return -1;
2370         }
2371
2372         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2373                 PRErrorCode err = PR_GetError();
2374                 Debug( LDAP_DEBUG_ANY, 
2375                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2376                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2377                 return -1;
2378         }
2379
2380         tlsm_free_config( ctx->tc_config );
2381         ctx->tc_config = NULL;
2382
2383         return 0;
2384 }
2385
2386 struct tls_data {
2387         tlsm_session            *session;
2388         Sockbuf_IO_Desc         *sbiod;
2389         /* there seems to be no portable way to determine if the
2390            sockbuf sd has been set to nonblocking mode - the
2391            call to ber_pvt_socket_set_nonblock() takes place
2392            before the tls socket is set up, so we cannot
2393            intercept that call either.
2394            On systems where fcntl is available, we can just
2395            F_GETFL and test for O_NONBLOCK.  On other systems,
2396            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2397            and just set this flag */
2398         PRBool              nonblock;
2399         /*
2400          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2401          * clients that send an SSLv2 client hello.  This message is not
2402          * tagged in any way, so NSS has no way to know if the incoming
2403          * message is a valid SSLv2 client hello or just some bogus data
2404          * (or cleartext LDAP).  We store the first byte read from the
2405          * client here.  The most common case will be a client sending
2406          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2407          * for example, if using ldapsearch -Z - if the starttls fails,
2408          * the client will fallback to plain cleartext LDAP.  So if we
2409          * see that the firstbyte is a valid LDAP tag, we can be
2410          * pretty sure this is happening.
2411          */
2412         ber_tag_t           firsttag;
2413         /*
2414          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2415          * when it is blocked, so we have to set a flag in the wrapped send
2416          * and recv calls that tells us what operation NSS was last blocked
2417          * on
2418          */
2419 #define TLSM_READ  1
2420 #define TLSM_WRITE 2
2421         int io_flag;
2422 };
2423
2424 static struct tls_data *
2425 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2426 {
2427         struct tls_data         *p;
2428         PRFileDesc *myfd;
2429
2430         if ( !fd ) {
2431                 return NULL;
2432         }
2433
2434         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2435
2436         if ( !myfd ) {
2437                 return NULL;
2438         }
2439
2440         p = (struct tls_data *)myfd->secret;
2441
2442         return p;
2443 }
2444
2445 static int
2446 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2447 {
2448         struct tls_data         *p;
2449
2450         if ( thebyte ) {
2451                 *thebyte = LBER_DEFAULT;
2452         }
2453
2454         p = tlsm_get_pvt_tls_data( fd );
2455         if ( p == NULL || p->sbiod == NULL ) {
2456                 return 0;
2457         }
2458
2459         if ( p->firsttag == LBER_SEQUENCE ) {
2460                 if ( thebyte ) {
2461                         *thebyte = p->firsttag;
2462                 }
2463                 return 1;
2464         }
2465
2466         return 0;
2467 }
2468
2469 static tls_session *
2470 tlsm_session_new ( tls_ctx * ctx, int is_server )
2471 {
2472         tlsm_ctx *c = (tlsm_ctx *)ctx;
2473         tlsm_session *session;
2474         PRFileDesc *fd;
2475         PRStatus status;
2476         int rc;
2477
2478         c->tc_is_server = is_server;
2479         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2480         if ( PR_SUCCESS != status ) {
2481                 PRErrorCode err = PR_GetError();
2482                 Debug( LDAP_DEBUG_ANY, 
2483                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2484                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2485                 return NULL;
2486         }
2487
2488         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2489         if ( !fd ) {
2490                 return NULL;
2491         }
2492
2493         session = SSL_ImportFD( c->tc_model, fd );
2494         if ( !session ) {
2495                 PR_DELETE( fd );
2496                 return NULL;
2497         }
2498
2499         rc = SSL_ResetHandshake( session, is_server );
2500         if ( rc ) {
2501                 PRErrorCode err = PR_GetError();
2502                 Debug( LDAP_DEBUG_TRACE, 
2503                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2504                            rc, err,
2505                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2506                 PR_DELETE( fd );
2507                 PR_Close( session );
2508                 session = NULL;
2509         }
2510
2511         return (tls_session *)session;
2512
2513
2514 static int
2515 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2516 {
2517         tlsm_session *s = (tlsm_session *)session;
2518         int rc;
2519         const char *op = is_accept ? "accept" : "connect";
2520
2521         if ( pem_module ) {
2522                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2523         }
2524         rc = SSL_ForceHandshake( s );
2525         if ( pem_module ) {
2526                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2527         }
2528         if ( rc ) {
2529                 PRErrorCode err = PR_GetError();
2530                 rc = -1;
2531                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2532                         ber_tag_t thetag = LBER_DEFAULT;
2533                         /* see if we are blocked because of a bogus packet */
2534                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2535                                 Debug( LDAP_DEBUG_ANY, 
2536                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2537                                            op, (unsigned int)thetag, 0 );
2538                                 /* reset error to something more descriptive */
2539                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2540                         }
2541                 } else {
2542                         Debug( LDAP_DEBUG_ANY, 
2543                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2544                                    op, errno, err );
2545                 }
2546         }
2547
2548         return rc;
2549 }
2550 static int
2551 tlsm_session_accept( tls_session *session )
2552 {
2553         return tlsm_session_accept_or_connect( session, 1 );
2554 }
2555
2556 static int
2557 tlsm_session_connect( LDAP *ld, tls_session *session )
2558 {
2559         return tlsm_session_accept_or_connect( session, 0 );
2560 }
2561
2562 static int
2563 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2564 {
2565         int prerror = PR_GetError();
2566
2567         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2568                 tlsm_session *s = (tlsm_session *)session;
2569                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2570
2571                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2572                         sb->sb_trans_needs_read = 1;
2573                         return 1;
2574                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2575                         sb->sb_trans_needs_write = 1;
2576                         return 1;
2577                 }
2578         }
2579
2580         return 0;
2581 }
2582
2583 static char *
2584 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2585 {
2586         int i;
2587         int prerror = PR_GetError();
2588
2589         i = PR_GetErrorTextLength();
2590         if ( i > len ) {
2591                 char *msg = LDAP_MALLOC( i+1 );
2592                 PR_GetErrorText( msg );
2593                 memcpy( buf, msg, len );
2594                 LDAP_FREE( msg );
2595         } else if ( i ) {
2596                 PR_GetErrorText( buf );
2597         } else if ( prerror ) {
2598                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2599                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2600         }
2601
2602         return ( i > 0 ) ? buf : NULL;
2603 }
2604
2605 static int
2606 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2607 {
2608         tlsm_session *s = (tlsm_session *)session;
2609         CERTCertificate *cert;
2610
2611         cert = SSL_LocalCertificate( s );
2612         if (!cert) return LDAP_INVALID_CREDENTIALS;
2613
2614         der_dn->bv_val = (char *)cert->derSubject.data;
2615         der_dn->bv_len = cert->derSubject.len;
2616         CERT_DestroyCertificate( cert );
2617         return 0;
2618 }
2619
2620 static int
2621 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2622 {
2623         tlsm_session *s = (tlsm_session *)session;
2624         CERTCertificate *cert;
2625
2626         cert = SSL_PeerCertificate( s );
2627         if (!cert) return LDAP_INVALID_CREDENTIALS;
2628         
2629         der_dn->bv_val = (char *)cert->derSubject.data;
2630         der_dn->bv_len = cert->derSubject.len;
2631         CERT_DestroyCertificate( cert );
2632         return 0;
2633 }
2634
2635 /* what kind of hostname were we given? */
2636 #define IS_DNS  0
2637 #define IS_IP4  1
2638 #define IS_IP6  2
2639
2640 static int
2641 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2642 {
2643         tlsm_session *s = (tlsm_session *)session;
2644         CERTCertificate *cert;
2645         const char *name, *domain = NULL, *ptr;
2646         int ret, ntype = IS_DNS, nlen, dlen;
2647 #ifdef LDAP_PF_INET6
2648         struct in6_addr addr;
2649 #else
2650         struct in_addr addr;
2651 #endif
2652         SECItem altname;
2653         SECStatus rv;
2654
2655         if( ldap_int_hostname &&
2656                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2657         {
2658                 name = ldap_int_hostname;
2659         } else {
2660                 name = name_in;
2661         }
2662         nlen = strlen( name );
2663
2664         cert = SSL_PeerCertificate( s );
2665         if (!cert) {
2666                 Debug( LDAP_DEBUG_ANY,
2667                         "TLS: unable to get peer certificate.\n",
2668                         0, 0, 0 );
2669                 /* if this was a fatal condition, things would have
2670                  * aborted long before now.
2671                  */
2672                 return LDAP_SUCCESS;
2673         }
2674
2675 #ifdef LDAP_PF_INET6
2676         if (inet_pton(AF_INET6, name, &addr)) {
2677                 ntype = IS_IP6;
2678         } else 
2679 #endif
2680         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2681                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2682         }
2683         if (ntype == IS_DNS ) {
2684                 domain = strchr( name, '.' );
2685                 if ( domain )
2686                         dlen = nlen - ( domain - name );
2687         }
2688
2689         ret = LDAP_LOCAL_ERROR;
2690
2691         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2692                 &altname );
2693         if ( rv == SECSuccess && altname.data ) {
2694                 PRArenaPool *arena;
2695                 CERTGeneralName *names, *cur;
2696
2697                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2698                 if ( !arena ) {
2699                         ret = LDAP_NO_MEMORY;
2700                         goto fail;
2701                 }
2702
2703                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2704                 if ( !cur )
2705                         goto altfail;
2706
2707                 do {
2708                         char *host;
2709                         int hlen;
2710
2711                         /* ignore empty */
2712                         if ( !cur->name.other.len ) continue;
2713
2714                         host = (char *)cur->name.other.data;
2715                         hlen = cur->name.other.len;
2716
2717                         if ( cur->type == certDNSName ) {
2718                                 if ( ntype != IS_DNS )  continue;
2719
2720                                 /* is this an exact match? */
2721                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2722                                         ret = LDAP_SUCCESS;
2723                                         break;
2724                                 }
2725
2726                                 /* is this a wildcard match? */
2727                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2728                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2729                                         ret = LDAP_SUCCESS;
2730                                         break;
2731                                 }
2732                         } else if ( cur->type == certIPAddress ) {
2733                                 if ( ntype == IS_DNS )  continue;
2734                                 
2735 #ifdef LDAP_PF_INET6
2736                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2737                                         continue;
2738                                 } else
2739 #endif
2740                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2741                                         continue;
2742                                 }
2743                                 if (!memcmp(host, &addr, hlen)) {
2744                                         ret = LDAP_SUCCESS;
2745                                         break;
2746                                 }
2747                         }
2748                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2749 altfail:
2750                 PORT_FreeArena( arena, PR_FALSE );
2751                 SECITEM_FreeItem( &altname, PR_FALSE );
2752         }
2753         /* no altnames matched, try the CN */
2754         if ( ret != LDAP_SUCCESS ) {
2755                 /* find the last CN */
2756                 CERTRDN *rdn, **rdns;
2757                 CERTAVA *lastava = NULL;
2758                 char buf[2048];
2759
2760                 buf[0] = '\0';
2761                 rdns = cert->subject.rdns;
2762                 while ( rdns && ( rdn = *rdns++ )) {
2763                         CERTAVA *ava, **avas = rdn->avas;
2764                         while ( avas && ( ava = *avas++ )) {
2765                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2766                                         lastava = ava;
2767                         }
2768                 }
2769                 if ( lastava ) {
2770                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2771                         if ( av ) {
2772                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2773                                         ret = LDAP_SUCCESS;
2774                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2775                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2776                                                 (char *)(av->data+1), dlen )) {
2777                                         ret = LDAP_SUCCESS;
2778                                 } else {
2779                                         int len = av->len;
2780                                         if ( len >= sizeof(buf) )
2781                                                 len = sizeof(buf)-1;
2782                                         memcpy( buf, av->data, len );
2783                                         buf[len] = '\0';
2784                                 }
2785                                 SECITEM_FreeItem( av, PR_TRUE );
2786                         }
2787                 }
2788                 if ( ret != LDAP_SUCCESS ) {
2789                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2790                                 "common name in certificate (%s).\n", 
2791                                 name, buf, 0 );
2792                         ret = LDAP_CONNECT_ERROR;
2793                         if ( ld->ld_error ) {
2794                                 LDAP_FREE( ld->ld_error );
2795                         }
2796                         ld->ld_error = LDAP_STRDUP(
2797                                 _("TLS: hostname does not match CN in peer certificate"));
2798                 }
2799         }
2800
2801 fail:
2802         CERT_DestroyCertificate( cert );
2803         return ret;
2804 }
2805
2806 static int
2807 tlsm_session_strength( tls_session *session )
2808 {
2809         tlsm_session *s = (tlsm_session *)session;
2810         int rc, keySize;
2811
2812         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2813                 NULL, NULL );
2814         return rc ? 0 : keySize;
2815 }
2816
2817 /*
2818  * TLS support for LBER Sockbufs
2819  */
2820
2821 static PRStatus PR_CALLBACK
2822 tlsm_PR_Close(PRFileDesc *fd)
2823 {
2824         int rc = PR_SUCCESS;
2825
2826         /* we don't need to actually close anything here, just
2827            pop our io layer off the stack */
2828         fd->secret = NULL; /* must have been freed before calling PR_Close */
2829         if ( fd->lower ) {
2830                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2831                 /* if we are not the last layer, pass the close along */
2832                 if ( fd ) {
2833                         if ( fd->dtor ) {
2834                                 fd->dtor( fd );
2835                         }
2836                         rc = fd->methods->close( fd );
2837                 }
2838         } else {
2839                 /* we are the last layer - just call our dtor */
2840                 fd->dtor(fd);
2841         }
2842
2843         return rc;
2844 }
2845
2846 static PRStatus PR_CALLBACK
2847 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2848 {
2849         int rc = PR_SUCCESS;
2850
2851         if ( fd->lower ) {
2852                 rc = PR_Shutdown( fd->lower, how );
2853         }
2854
2855         return rc;
2856 }
2857
2858 static int PR_CALLBACK
2859 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2860          PRIntervalTime timeout)
2861 {
2862         struct tls_data         *p;
2863         int rc;
2864
2865         if ( buf == NULL || len <= 0 ) return 0;
2866
2867         p = tlsm_get_pvt_tls_data( fd );
2868
2869         if ( p == NULL || p->sbiod == NULL ) {
2870                 return 0;
2871         }
2872
2873         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2874         if (rc <= 0) {
2875                 tlsm_map_error( errno );
2876                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2877                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2878                 } else if ( errno ) { /* real error */
2879                         Debug( LDAP_DEBUG_TRACE, 
2880                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2881                                rc, errno, STRERROR(errno) );
2882                 }
2883         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
2884                 p->firsttag = (ber_tag_t)*((char *)buf);
2885         }
2886         p->io_flag = TLSM_READ;
2887
2888         return rc;
2889 }
2890
2891 static int PR_CALLBACK
2892 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2893          PRIntervalTime timeout)
2894 {
2895         struct tls_data         *p;
2896         int rc;
2897
2898         if ( buf == NULL || len <= 0 ) return 0;
2899
2900         p = tlsm_get_pvt_tls_data( fd );
2901
2902         if ( p == NULL || p->sbiod == NULL ) {
2903                 return 0;
2904         }
2905
2906         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
2907         if (rc <= 0) {
2908                 tlsm_map_error( errno );
2909                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2910                         p->nonblock = PR_TRUE;
2911                 } else if ( errno ) { /* real error */
2912                         Debug( LDAP_DEBUG_TRACE, 
2913                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
2914                                rc, errno, STRERROR(errno) );
2915                 }
2916         }
2917         p->io_flag = TLSM_WRITE;
2918
2919         return rc;
2920 }
2921
2922 static int PR_CALLBACK
2923 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
2924 {
2925         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2926 }
2927
2928 static int PR_CALLBACK
2929 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
2930 {
2931         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2932 }
2933
2934 static PRStatus PR_CALLBACK
2935 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
2936 {
2937         struct tls_data         *p;
2938         ber_socklen_t len;
2939
2940         p = tlsm_get_pvt_tls_data( fd );
2941
2942         if ( p == NULL || p->sbiod == NULL ) {
2943                 return PR_FAILURE;
2944         }
2945         len = sizeof(PRNetAddr);
2946         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
2947 }
2948
2949 static PRStatus PR_CALLBACK
2950 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
2951 {
2952         struct tls_data         *p;
2953         p = tlsm_get_pvt_tls_data( fd );
2954
2955         if ( p == NULL || data == NULL ) {
2956                 return PR_FAILURE;
2957         }
2958
2959         /* only the nonblocking option is supported at this time
2960            MozNSS SSL code needs it */
2961         if ( data->option != PR_SockOpt_Nonblocking ) {
2962                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2963                 return PR_FAILURE;
2964         }
2965 #ifdef HAVE_FCNTL
2966         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
2967         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
2968 #else /* punt :P */
2969         data->value.non_blocking = p->nonblock;
2970 #endif
2971         return PR_SUCCESS;
2972 }
2973
2974 static PRStatus PR_CALLBACK
2975 tlsm_PR_prs_unimp()
2976 {
2977     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2978     return PR_FAILURE;
2979 }
2980
2981 static PRFileDesc * PR_CALLBACK
2982 tlsm_PR_pfd_unimp()
2983 {
2984     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2985     return NULL;
2986 }
2987
2988 static PRInt16 PR_CALLBACK
2989 tlsm_PR_i16_unimp()
2990 {
2991     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2992     return SECFailure;
2993 }
2994
2995 static PRInt32 PR_CALLBACK
2996 tlsm_PR_i32_unimp()
2997 {
2998     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2999     return SECFailure;
3000 }
3001
3002 static PRInt64 PR_CALLBACK
3003 tlsm_PR_i64_unimp()
3004 {
3005     PRInt64 res;
3006
3007     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3008     LL_I2L(res, -1L);
3009     return res;
3010 }
3011
3012 static const PRIOMethods tlsm_PR_methods = {
3013     PR_DESC_LAYERED,
3014     tlsm_PR_Close,                      /* close        */
3015     tlsm_PR_Read,                       /* read         */
3016     tlsm_PR_Write,                      /* write        */
3017     tlsm_PR_i32_unimp,          /* available    */
3018     tlsm_PR_i64_unimp,          /* available64  */
3019     tlsm_PR_prs_unimp,          /* fsync        */
3020     tlsm_PR_i32_unimp,          /* seek         */
3021     tlsm_PR_i64_unimp,          /* seek64       */
3022     tlsm_PR_prs_unimp,          /* fileInfo     */
3023     tlsm_PR_prs_unimp,          /* fileInfo64   */
3024     tlsm_PR_i32_unimp,          /* writev       */
3025     tlsm_PR_prs_unimp,          /* connect      */
3026     tlsm_PR_pfd_unimp,          /* accept       */
3027     tlsm_PR_prs_unimp,          /* bind         */
3028     tlsm_PR_prs_unimp,          /* listen       */
3029     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3030     tlsm_PR_Recv,                       /* recv         */
3031     tlsm_PR_Send,                       /* send         */
3032     tlsm_PR_i32_unimp,          /* recvfrom     */
3033     tlsm_PR_i32_unimp,          /* sendto       */
3034     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3035     tlsm_PR_i32_unimp,          /* acceptread   */
3036     tlsm_PR_i32_unimp,          /* transmitfile */
3037     tlsm_PR_prs_unimp,          /* getsockname  */
3038     tlsm_PR_GetPeerName,        /* getpeername  */
3039     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3040     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3041     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3042     tlsm_PR_i32_unimp,          /* setsocketoption   */
3043     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3044     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3045     tlsm_PR_i32_unimp,          /* reserved for future use */
3046     tlsm_PR_i32_unimp,          /* reserved for future use */
3047     tlsm_PR_i32_unimp,          /* reserved for future use */
3048     tlsm_PR_i32_unimp           /* reserved for future use */
3049 };
3050
3051 /*
3052  * Initialize TLS subsystem. Should be called only once.
3053  * See tlsm_deferred_init for the bulk of the init process
3054  */
3055 static int
3056 tlsm_init( void )
3057 {
3058         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3059
3060         PR_Init(0, 0, 0);
3061
3062         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3063
3064         /*
3065          * There are some applications that acquire a crypto context in the parent process
3066          * and expect that crypto context to work after a fork().  This does not work
3067          * with NSS using strict PKCS11 compliance mode.  We set this environment
3068          * variable here to tell the software encryption module/token to allow crypto
3069          * contexts to persist across a fork().  However, if you are using some other
3070          * module or encryption device that supports and expects full PKCS11 semantics,
3071          * the only recourse is to rewrite the application with atfork() handlers to save
3072          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3073          * context in the child.
3074          */
3075         if ( !nofork ) {
3076                 /* will leak one time */
3077                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3078                 PR_SetEnv( noforkenvvar );
3079         }
3080
3081         return 0;
3082 }
3083
3084 static int
3085 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3086 {
3087         struct tls_data         *p;
3088         tlsm_session    *session = arg;
3089         PRFileDesc *fd;
3090
3091         assert( sbiod != NULL );
3092
3093         p = LBER_MALLOC( sizeof( *p ) );
3094         if ( p == NULL ) {
3095                 return -1;
3096         }
3097
3098         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3099         if ( !fd ) {
3100                 LBER_FREE( p );
3101                 return -1;
3102         }
3103
3104         fd->secret = (PRFilePrivate *)p;
3105         p->session = session;
3106         p->sbiod = sbiod;
3107         p->firsttag = LBER_DEFAULT;
3108         sbiod->sbiod_pvt = p;
3109         return 0;
3110 }
3111
3112 static int
3113 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
3114 {
3115         struct tls_data         *p;
3116         
3117         assert( sbiod != NULL );
3118         assert( sbiod->sbiod_pvt != NULL );
3119
3120         p = (struct tls_data *)sbiod->sbiod_pvt;
3121         PR_Close( p->session );
3122         LBER_FREE( sbiod->sbiod_pvt );
3123         sbiod->sbiod_pvt = NULL;
3124         return 0;
3125 }
3126
3127 static int
3128 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3129 {
3130         struct tls_data         *p;
3131         
3132         assert( sbiod != NULL );
3133         assert( sbiod->sbiod_pvt != NULL );
3134
3135         p = (struct tls_data *)sbiod->sbiod_pvt;
3136         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3137         return 0;
3138 }
3139
3140 static int
3141 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3142 {
3143         struct tls_data         *p;
3144         
3145         assert( sbiod != NULL );
3146         assert( sbiod->sbiod_pvt != NULL );
3147
3148         p = (struct tls_data *)sbiod->sbiod_pvt;
3149         
3150         if ( opt == LBER_SB_OPT_GET_SSL ) {
3151                 *((tlsm_session **)arg) = p->session;
3152                 return 1;
3153                 
3154         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3155                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3156                         return 1;
3157                 }
3158                 
3159         }
3160         
3161         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3162 }
3163
3164 static ber_slen_t
3165 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3166 {
3167         struct tls_data         *p;
3168         ber_slen_t              ret;
3169         int                     err;
3170
3171         assert( sbiod != NULL );
3172         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3173
3174         p = (struct tls_data *)sbiod->sbiod_pvt;
3175
3176         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3177         if ( ret < 0 ) {
3178                 err = PR_GetError();
3179                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3180                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3181                         sock_errset(EWOULDBLOCK);
3182                 }
3183         } else {
3184                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3185         }
3186         return ret;
3187 }
3188
3189 static ber_slen_t
3190 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3191 {
3192         struct tls_data         *p;
3193         ber_slen_t              ret;
3194         int                     err;
3195
3196         assert( sbiod != NULL );
3197         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3198
3199         p = (struct tls_data *)sbiod->sbiod_pvt;
3200
3201         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3202         if ( ret < 0 ) {
3203                 err = PR_GetError();
3204                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3205                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3206                         sock_errset(EWOULDBLOCK);
3207                         ret = 0;
3208                 }
3209         } else {
3210                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3211         }
3212         return ret;
3213 }
3214
3215 static Sockbuf_IO tlsm_sbio =
3216 {
3217         tlsm_sb_setup,          /* sbi_setup */
3218         tlsm_sb_remove,         /* sbi_remove */
3219         tlsm_sb_ctrl,           /* sbi_ctrl */
3220         tlsm_sb_read,           /* sbi_read */
3221         tlsm_sb_write,          /* sbi_write */
3222         tlsm_sb_close           /* sbi_close */
3223 };
3224
3225 tls_impl ldap_int_tls_impl = {
3226         "MozNSS",
3227
3228         tlsm_init,
3229         tlsm_destroy,
3230
3231         tlsm_ctx_new,
3232         tlsm_ctx_ref,
3233         tlsm_ctx_free,
3234         tlsm_ctx_init,
3235
3236         tlsm_session_new,
3237         tlsm_session_connect,
3238         tlsm_session_accept,
3239         tlsm_session_upflags,
3240         tlsm_session_errmsg,
3241         tlsm_session_my_dn,
3242         tlsm_session_peer_dn,
3243         tlsm_session_chkhost,
3244         tlsm_session_strength,
3245
3246         &tlsm_sbio,
3247
3248 #ifdef LDAP_R_COMPILE
3249         tlsm_thr_init,
3250 #else
3251         NULL,
3252 #endif
3253
3254         0
3255 };
3256
3257 #endif /* HAVE_MOZNSS */
3258 /*
3259   emacs settings
3260   Local Variables:
3261   indent-tabs-mode: t
3262   tab-width: 4
3263   End:
3264 */