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