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