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