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