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