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