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