]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
e713459448defa5ce0e5bed84f29fbd494c44aca
[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 SECStatus
934 tlsm_nss_shutdown_cb( void *appData, void *nssData )
935 {
936         SECStatus rc = SECSuccess;
937
938         SSL_ShutdownServerSessionIDCache();
939         SSL_ClearSessionCache();
940
941         if ( pem_module ) {
942                 SECMOD_UnloadUserModule( pem_module );
943                 SECMOD_DestroyModule( pem_module );
944                 pem_module = NULL;
945         }
946         return rc;
947 }
948
949 static int
950 tlsm_init_pem_module( void )
951 {
952         int rc = 0;
953         char *fullname = NULL;
954         char *configstring = NULL;
955
956         if ( pem_module ) {
957                 return rc;
958         }
959
960         /* not loaded - load it */
961         /* get the system dependent library name */
962         fullname = PR_GetLibraryName( NULL, PEM_LIBRARY );
963         /* Load our PKCS#11 module */
964         configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname );
965         PL_strfree( fullname );
966
967         pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
968         PR_smprintf_free( configstring );
969
970         if ( !pem_module || !pem_module->loaded ) {
971                 if ( pem_module ) {
972                         SECMOD_DestroyModule( pem_module );
973                         pem_module = NULL;
974                 }
975                 rc = -1;
976         }
977
978         return rc;
979 }
980
981 static void
982 tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
983 {
984         int idx = ctx->tc_n_pem_objs;
985         ctx->tc_n_pem_objs++;
986         ctx->tc_pem_objs = (PK11GenericObject **)
987                 PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
988         ctx->tc_pem_objs[idx] = obj;                                                                                                              
989 }
990
991 static void
992 tlsm_free_pem_objs( tlsm_ctx *ctx )
993 {
994         /* free in reverse order of allocation */
995         while ( ctx->tc_n_pem_objs-- ) {
996                 PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
997                 ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
998         }
999         PORT_Free(ctx->tc_pem_objs);
1000         ctx->tc_pem_objs = NULL;
1001         ctx->tc_n_pem_objs = 0;
1002 }
1003
1004 static int
1005 tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
1006 {
1007         CK_SLOT_ID slotID;
1008         PK11SlotInfo *slot = NULL;
1009         PK11GenericObject *rv;
1010         CK_ATTRIBUTE *attrs;
1011         CK_ATTRIBUTE theTemplate[20];
1012         CK_BBOOL cktrue = CK_TRUE;
1013         CK_BBOOL ckfalse = CK_FALSE;
1014         CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
1015         char tmpslotname[64];
1016         char *slotname = NULL;
1017         const char *ptr = NULL;
1018         char sep = PR_GetDirectorySeparator();
1019         PRFileInfo fi;
1020         PRStatus status;
1021
1022         memset( &fi, 0, sizeof(fi) );
1023         status = PR_GetFileInfo( filename, &fi );
1024         if ( PR_SUCCESS != status) {
1025                 PRErrorCode errcode = PR_GetError();
1026                 Debug( LDAP_DEBUG_ANY,
1027                            "TLS: could not read certificate file %s - error %d:%s.\n",
1028                            filename, errcode,
1029                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1030                 return -1;
1031         }
1032
1033         if ( fi.type != PR_FILE_FILE ) {
1034                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1035                 Debug( LDAP_DEBUG_ANY,
1036                            "TLS: error: the certificate file %s is not a file.\n",
1037                            filename, 0 ,0 );
1038                 return -1;
1039         }
1040
1041         attrs = theTemplate;
1042
1043         if ( isca ) {
1044                 slotID = 0; /* CA and trust objects use slot 0 */
1045                 PR_snprintf( tmpslotname, sizeof(tmpslotname), TLSM_PEM_TOKEN_FMT, slotID );
1046                 slotname = tmpslotname;
1047         } else {
1048                 if ( ctx->tc_slotname == NULL ) { /* need new slot */
1049                         slotID = ++tlsm_slot_count;
1050                         ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID );
1051                 }
1052                 slotname = ctx->tc_slotname;
1053
1054                 if ( ( ptr = PL_strrchr( filename, sep ) ) ) {
1055                         PL_strfree( ctx->tc_certname );
1056                         ++ptr;
1057                         ctx->tc_certname = PR_smprintf( "%s:%s", slotname, ptr );
1058                 }
1059         }
1060
1061         slot = PK11_FindSlotByName( slotname );
1062
1063         if ( !slot ) {
1064                 PRErrorCode errcode = PR_GetError();
1065                 Debug( LDAP_DEBUG_ANY,
1066                            "TLS: could not find the slot for certificate %s - error %d:%s.\n",
1067                            ctx->tc_certname, errcode,
1068                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1069                 return -1;
1070         }
1071
1072         PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
1073         PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1074         PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++;
1075         if ( isca ) {
1076                 PK11_SETATTRS( attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1077         } else {
1078                 PK11_SETATTRS( attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); attrs++;
1079         }
1080         /* This loads the certificate in our PEM module into the appropriate
1081          * slot.
1082          */
1083         rv = PK11_CreateGenericObject( slot, theTemplate, 4, PR_FALSE /* isPerm */ );
1084
1085         PK11_FreeSlot( slot );
1086
1087         if ( !rv ) {
1088                 PRErrorCode errcode = PR_GetError();
1089                 Debug( LDAP_DEBUG_ANY,
1090                            "TLS: could not add the certificate %s - error %d:%s.\n",
1091                            ctx->tc_certname, errcode,
1092                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1093                 return -1;
1094         }
1095
1096         tlsm_add_pem_obj( ctx, rv );
1097
1098         return 0;
1099 }
1100
1101 static int
1102 tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
1103 {
1104         CK_SLOT_ID slotID;
1105         PK11SlotInfo * slot = NULL;
1106         PK11GenericObject *rv;
1107         CK_ATTRIBUTE *attrs;
1108         CK_ATTRIBUTE theTemplate[20];
1109         CK_BBOOL cktrue = CK_TRUE;
1110         CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
1111         int retcode = 0;
1112         PRFileInfo fi;
1113         PRStatus status;
1114
1115         memset( &fi, 0, sizeof(fi) );
1116         status = PR_GetFileInfo( filename, &fi );
1117         if ( PR_SUCCESS != status) {
1118                 PRErrorCode errcode = PR_GetError();
1119                 Debug( LDAP_DEBUG_ANY,
1120                            "TLS: could not read key file %s - error %d:%s.\n",
1121                            filename, errcode,
1122                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1123                 return -1;
1124         }
1125
1126         if ( fi.type != PR_FILE_FILE ) {
1127                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1128                 Debug( LDAP_DEBUG_ANY,
1129                            "TLS: error: the key file %s is not a file.\n",
1130                            filename, 0 ,0 );
1131                 return -1;
1132         }
1133
1134         attrs = theTemplate;
1135
1136         if ( ctx->tc_slotname == NULL ) { /* need new slot */
1137                 slotID = ++tlsm_slot_count;
1138                 ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID );
1139         }
1140         slot = PK11_FindSlotByName( ctx->tc_slotname );
1141
1142         if ( !slot ) {
1143                 PRErrorCode errcode = PR_GetError();
1144                 Debug( LDAP_DEBUG_ANY,
1145                            "TLS: could not find the slot %s for the private key - error %d:%s.\n",
1146                            ctx->tc_slotname, errcode,
1147                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1148                 return -1;
1149         }
1150
1151         PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
1152         PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1153         PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++;
1154         rv = PK11_CreateGenericObject( slot, theTemplate, 3, PR_FALSE /* isPerm */ );
1155
1156         if ( !rv ) {
1157                 PRErrorCode errcode = PR_GetError();
1158                 Debug( LDAP_DEBUG_ANY,
1159                            "TLS: could not add the certificate %s - error %d:%s.\n",
1160                            ctx->tc_certname, errcode,
1161                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1162                 retcode = -1;
1163         } else {
1164                 /* When adding an encrypted key the PKCS#11 will be set as removed */
1165                 /* This will force the token to be seen as re-inserted */
1166                 SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
1167                 PK11_IsPresent( slot );
1168                 retcode = 0;
1169         }
1170
1171         PK11_FreeSlot( slot );
1172
1173         if ( !retcode ) {
1174                 tlsm_add_pem_obj( ctx, rv );
1175         }
1176         return retcode;
1177 }
1178
1179 static int
1180 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
1181 {
1182         PRBool isca = PR_TRUE;
1183         PRStatus status = PR_FAILURE;
1184         PRErrorCode errcode = PR_SUCCESS;
1185
1186         if ( cacertfile ) {
1187                 int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca );
1188                 if ( rc ) {
1189                         errcode = PR_GetError();
1190                         Debug( LDAP_DEBUG_ANY,
1191                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1192                                    cacertfile, errcode,
1193                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1194                 } else {
1195                         Debug( LDAP_DEBUG_TRACE,
1196                                    "TLS: loaded CA certificate file %s.\n",
1197                                    cacertfile, 0, 0 );
1198                         status = PR_SUCCESS; /* have at least one good CA - we can proceed */
1199                 }
1200         }
1201
1202         if ( cacertdir ) {
1203                 PRFileInfo fi;
1204                 PRDir *dir;
1205                 PRDirEntry *entry;
1206                 PRStatus fistatus = PR_FAILURE;
1207
1208                 memset( &fi, 0, sizeof(fi) );
1209                 fistatus = PR_GetFileInfo( cacertdir, &fi );
1210                 if ( PR_SUCCESS != fistatus) {
1211                         errcode = PR_GetError();
1212                         Debug( LDAP_DEBUG_ANY,
1213                                    "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
1214                                    cacertdir, errcode,
1215                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1216                         goto done;
1217                 }
1218
1219                 if ( fi.type != PR_FILE_DIRECTORY ) {
1220                         Debug( LDAP_DEBUG_ANY,
1221                                    "TLS: error: the CA certificate directory %s is not a directory.\n",
1222                                    cacertdir, 0 ,0 );
1223                         goto done;
1224                 }
1225
1226                 dir = PR_OpenDir( cacertdir );
1227                 if ( NULL == dir ) {
1228                         errcode = PR_GetError();
1229                         Debug( LDAP_DEBUG_ANY,
1230                                    "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
1231                                    cacertdir, errcode,
1232                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1233                         goto done;
1234                 }
1235
1236                 do {
1237                         entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
1238                         if ( NULL != entry ) {
1239                                 char *fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
1240                                 if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) {
1241                                         Debug( LDAP_DEBUG_TRACE,
1242                                                    "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
1243                                                    fullpath, cacertdir, 0 );
1244                                         status = PR_SUCCESS; /* found at least 1 valid CA file in the dir */
1245                                 } else {
1246                                         errcode = PR_GetError();
1247                                         Debug( LDAP_DEBUG_TRACE,
1248                                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1249                                                    fullpath, errcode,
1250                                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1251                                 }
1252                                 PR_smprintf_free( fullpath );
1253                         }
1254                 } while ( NULL != entry );
1255                 PR_CloseDir( dir );
1256         }
1257 done:
1258         if ( status != PR_SUCCESS ) {
1259                 const char *fmtstr = NULL;
1260                 if ( cacertfile && cacertdir ) {
1261                         fmtstr = "TLS: did not find any valid CA certificates in %s or %s\n";
1262                 } else {
1263                         fmtstr = "TLS: did not find any valid CA certificates in %s%s\n";
1264                 }
1265                 Debug( LDAP_DEBUG_ANY, fmtstr, cacertdir ? cacertdir : "",
1266                            cacertfile ? cacertfile : "", 0 );
1267                 return -1;
1268         }
1269
1270         return 0;
1271 }
1272
1273 /*
1274  * NSS supports having multiple cert/key databases in the same
1275  * directory, each one having a unique string prefix e.g.
1276  * slapd-01-cert8.db - the prefix here is "slapd-01-"
1277  * this function examines the given certdir - if it looks like
1278  * /path/to/directory/prefix it will return the
1279  * /path/to/directory part in realcertdir, and the prefix in prefix
1280  */
1281 static void
1282 tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
1283 {
1284         char sep = PR_GetDirectorySeparator();
1285         char *ptr = NULL;
1286         struct PRFileInfo prfi;
1287         PRStatus prc;
1288
1289         *realcertdir = (char *)certdir; /* default is the one passed in */
1290
1291         /* if certdir is not given, just return */
1292         if ( !certdir ) {
1293                 return;
1294         }
1295
1296         prc = PR_GetFileInfo( certdir, &prfi );
1297         /* if certdir exists (file or directory) then it cannot specify a prefix */
1298         if ( prc == PR_SUCCESS ) {
1299                 return;
1300         }
1301
1302         /* if certdir was given, and there is a '/' in certdir, see if there
1303            is anything after the last '/' - if so, assume it is the prefix */
1304         if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
1305                 *realcertdir = PL_strndup( certdir, ptr-certdir );
1306                 *prefix = PL_strdup( ptr+1 );
1307         }
1308
1309         return;
1310 }
1311
1312 /*
1313  * This is the part of the init we defer until we get the
1314  * actual security configuration information.  This is
1315  * only called once, protected by a PRCallOnce
1316  * NOTE: This must be done before the first call to SSL_ImportFD,
1317  * especially the setting of the policy
1318  * NOTE: This must be called after fork()
1319  */
1320 static int
1321 tlsm_deferred_init( void *arg )
1322 {
1323         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1324         struct ldaptls *lt = ctx->tc_config;
1325         const char *securitydirs[3];
1326         int ii;
1327         int nn;
1328         PRErrorCode errcode = 1;
1329 #ifdef HAVE_NSS_INITCONTEXT
1330         NSSInitParameters initParams;
1331         NSSInitContext *initctx = NULL;
1332 #endif
1333         SECStatus rc;
1334         int done = 0;
1335
1336 #ifdef HAVE_NSS_INITCONTEXT
1337         memset( &initParams, 0, sizeof( initParams ) );
1338         initParams.length = sizeof( initParams );
1339 #endif /* HAVE_NSS_INITCONTEXT */
1340
1341 #ifndef HAVE_NSS_INITCONTEXT
1342         if ( !NSS_IsInitialized() ) {
1343 #endif /* HAVE_NSS_INITCONTEXT */
1344                 /*
1345                   MOZNSS_DIR will override everything else - you can
1346                   always set MOZNSS_DIR to force the use of this
1347                   directory
1348                   If using MOZNSS, specify the location of the moznss db dir
1349                   in the cacertdir directive of the OpenLDAP configuration.
1350                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1351                   find a security dir to use based on the current
1352                   settings
1353                 */
1354                 nn = 0;
1355                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1356                 securitydirs[nn++] = lt->lt_cacertdir;
1357                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1358                 for ( ii = 0; !done && ( ii < nn ); ++ii ) {
1359                         char *realcertdir = NULL;
1360                         const char *defprefix = "";
1361                         char *prefix = (char *)defprefix;
1362                         const char *securitydir = securitydirs[ii];
1363                         if ( NULL == securitydir ) {
1364                                 continue;
1365                         }
1366
1367                         tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
1368 #ifdef HAVE_NSS_INITCONTEXT
1369 #ifdef INITCONTEXT_HACK
1370                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1371                                 rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1372                         } else {
1373                                 initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1374                                                                                    &initParams, NSS_INIT_READONLY );
1375                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1376                         }
1377 #else
1378                         initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1379                                                                            &initParams, NSS_INIT_READONLY );
1380                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1381 #endif
1382 #else
1383                         rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1384 #endif
1385
1386                         if ( rc != SECSuccess ) {
1387                                 errcode = PORT_GetError();
1388                                 Debug( LDAP_DEBUG_TRACE,
1389                                            "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1390                                            realcertdir, prefix, errcode );
1391                         } else {
1392                                 /* success */
1393                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
1394                                            realcertdir, prefix, 0 );
1395                                 errcode = 0;
1396                                 done = 1;
1397                         }
1398                         if ( realcertdir != securitydir ) {
1399                                 PL_strfree( realcertdir );
1400                         }
1401                         if ( prefix != defprefix ) {
1402                                 PL_strfree( prefix );
1403                         }
1404                 }
1405
1406                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1407 #ifdef HAVE_NSS_INITCONTEXT
1408                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1409 #ifdef INITCONTEXT_HACK
1410                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1411                                 rc = NSS_NoDB_Init( NULL );
1412                         } else {
1413                                 initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1414                                                                                    &initParams, flags );
1415                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1416                         }
1417 #else
1418                         initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1419                                                                            &initParams, flags );
1420                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1421 #endif
1422 #else
1423                         rc = NSS_NoDB_Init( NULL );
1424 #endif
1425                         if ( rc != SECSuccess ) {
1426                                 errcode = PORT_GetError();
1427                                 Debug( LDAP_DEBUG_ANY,
1428                                            "TLS: could not initialize moznss - error %d:%s.\n",
1429                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1430                                 return -1;
1431                         }
1432
1433 #ifdef HAVE_NSS_INITCONTEXT
1434                         ctx->tc_initctx = initctx;
1435 #endif
1436
1437                         /* initialize the PEM module */
1438                         if ( tlsm_init_pem_module() ) {
1439                                 errcode = PORT_GetError();
1440                                 Debug( LDAP_DEBUG_ANY,
1441                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1442                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1443                                 return -1;
1444                         }
1445
1446                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1447                                 return -1;
1448                         }
1449
1450                         ctx->tc_using_pem = PR_TRUE;
1451                 }
1452
1453 #ifdef HAVE_NSS_INITCONTEXT
1454                 if ( !ctx->tc_initctx ) {
1455                         ctx->tc_initctx = initctx;
1456                 }
1457 #endif
1458
1459                 NSS_SetDomesticPolicy();
1460
1461                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1462
1463                 /* register cleanup function */
1464                 /* delete the old one, if any */
1465                 NSS_UnregisterShutdown( tlsm_nss_shutdown_cb, NULL );
1466                 NSS_RegisterShutdown( tlsm_nss_shutdown_cb, NULL );
1467
1468 #ifndef HAVE_NSS_INITCONTEXT
1469         }
1470 #endif /* HAVE_NSS_INITCONTEXT */
1471
1472         return 0;
1473 }
1474
1475 static int
1476 tlsm_authenticate( tlsm_ctx *ctx, const char *certname, const char *pininfo )
1477 {
1478         const char *colon = NULL;
1479         char *token_name = NULL;
1480         PK11SlotInfo *slot = NULL;
1481         int rc = -1;
1482
1483         if ( !certname || !*certname ) {
1484                 return 0;
1485         }
1486
1487         if ( ( colon = PL_strchr( certname, ':' ) ) ) {
1488                 token_name = PL_strndup( certname, colon-certname );
1489         }
1490
1491         if ( token_name ) {
1492                 slot = PK11_FindSlotByName( token_name );
1493         } else {
1494                 slot = PK11_GetInternalKeySlot();
1495         }
1496
1497         if ( !slot ) {
1498                 PRErrorCode errcode = PR_GetError();
1499                 Debug( LDAP_DEBUG_ANY,
1500                            "TLS: could not find the slot for security token %s - error %d:%s.\n",
1501                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1502                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1503                 goto done;
1504         }
1505
1506         rc = tlsm_authenticate_to_slot( ctx, slot );
1507
1508 done:
1509         PL_strfree( token_name );
1510         if ( slot ) {
1511                 PK11_FreeSlot( slot );
1512         }
1513
1514         return rc;
1515 }
1516
1517 /*
1518  * Find and verify the certificate.
1519  * Either fd is given, in which case the cert will be taken from it via SSL_PeerCertificate
1520  * or certname is given, and it will be searched for by name
1521  */
1522 static int
1523 tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certname, int isServer, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
1524 {
1525         CERTCertificate *cert = NULL;
1526         int rc = -1;
1527         void *pin_arg = NULL;
1528         SECKEYPrivateKey *key = NULL;
1529
1530         pin_arg = SSL_RevealPinArg( fd );
1531         if ( certname ) {
1532                 cert = PK11_FindCertFromNickname( certname, pin_arg );
1533                 if ( !cert ) {
1534                         PRErrorCode errcode = PR_GetError();
1535                         Debug( LDAP_DEBUG_ANY,
1536                                    "TLS: error: the certificate %s could not be found in the database - error %d:%s\n",
1537                                    certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1538                         return -1;
1539                 }
1540         } else {
1541                 /* we are verifying the peer cert
1542                    we also need to swap the isServer meaning */
1543                 cert = SSL_PeerCertificate( fd );
1544                 if ( !cert ) {
1545                         PRErrorCode errcode = PR_GetError();
1546                         Debug( LDAP_DEBUG_ANY,
1547                                    "TLS: error: could not get the certificate from the peer connection - error %d:%s\n",
1548                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), NULL );
1549                         return -1;
1550                 }
1551                 isServer = !isServer; /* verify the peer's cert instead */
1552         }
1553
1554         if ( ctx->tc_slotname ) {
1555                 PK11SlotInfo *slot = PK11_FindSlotByName( ctx->tc_slotname );
1556                 key = PK11_FindPrivateKeyFromCert( slot, cert, NULL );
1557                 PK11_FreeSlot( slot );
1558         } else {
1559                 key = PK11_FindKeyByAnyCert( cert, pin_arg );
1560         }
1561
1562         if (key) {
1563                 SECCertificateUsage certUsage;
1564                 PRBool checkSig = PR_TRUE;
1565                 SECStatus status;
1566
1567                 if ( pRetKey ) {
1568                         *pRetKey = key; /* caller will deal with this */
1569                 } else {
1570                         SECKEY_DestroyPrivateKey( key );
1571                 }
1572                 if ( isServer ) {
1573                         certUsage = certificateUsageSSLServer;
1574                 } else {
1575                         certUsage = certificateUsageSSLClient;
1576                 }
1577                 if ( ctx->tc_verify_cert ) {
1578                         checkSig = PR_TRUE;
1579                 } else {
1580                         checkSig = PR_FALSE;
1581                 }
1582                 status = CERT_VerifyCertificateNow( ctx->tc_certdb, cert,
1583                                                                                         checkSig, certUsage,
1584                                                                                         pin_arg, NULL );
1585                 if ( status != SECSuccess ) {
1586                         /* NSS doesn't like self-signed CA certs that are also used for 
1587                            TLS/SSL server certs (such as generated by openssl req -x509)
1588                            CERT_VerifyCertificateNow returns SEC_ERROR_UNTRUSTED_ISSUER in that case
1589                            so, see if the cert and issuer are the same cert
1590                         */
1591                         PRErrorCode errcode = PR_GetError();
1592
1593                         if ( errcode == SEC_ERROR_UNTRUSTED_ISSUER ) {
1594                                 CERTCertificate *issuer = CERT_FindCertIssuer( cert, PR_Now(), certUsageSSLServer );
1595                                 if ( NULL == issuer ) {
1596                                         /* no issuer - fail */
1597                                         Debug( LDAP_DEBUG_ANY,
1598                                                    "TLS: error: the server certificate %s has no issuer - "
1599                                                    "please check this certificate for validity\n",
1600                                                    certname, 0, 0 );
1601                                 } else if ( CERT_CompareCerts( cert, issuer ) ) {
1602                                         /* self signed - warn and allow */
1603                                         status = SECSuccess;
1604                                         rc = 0;
1605                                         Debug( LDAP_DEBUG_ANY,
1606                                                    "TLS: warning: using self-signed server certificate %s\n",
1607                                                    certname, 0, 0 );
1608                                 }
1609                                 CERT_DestroyCertificate( issuer );
1610                         }
1611
1612                         if ( status != SECSuccess ) {
1613                                 Debug( LDAP_DEBUG_ANY,
1614                                            "TLS: error: the certificate %s is not valid - error %d:%s\n",
1615                                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1616                         }
1617                 } else {
1618                         rc = 0; /* success */
1619                 }
1620         } else {
1621                 PRErrorCode errcode = PR_GetError();
1622                 Debug( LDAP_DEBUG_ANY,
1623                            "TLS: error: could not find the private key for certificate %s - error %d:%s\n",
1624                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1625         }
1626
1627         if ( pRetCert ) {
1628                 *pRetCert = cert; /* caller will deal with this */
1629         } else {
1630                 CERT_DestroyCertificate( cert );
1631         }
1632
1633     return rc;
1634 }
1635
1636 static int
1637 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1638                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1639                                                    SECKEYPrivateKey **pRetKey )
1640 {
1641         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1642         int rc;
1643
1644         /* don't need caNames - this function will call CERT_VerifyCertificateNow
1645            which will verify the cert against the known CAs */
1646         rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
1647         if ( rc ) {
1648                 Debug( LDAP_DEBUG_ANY,
1649                            "TLS: error: unable to perform client certificate authentication for "
1650                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1651                 return SECFailure;
1652         }
1653
1654         return SECSuccess;
1655 }
1656
1657 /*
1658  * ctx must have a tc_model that is valid
1659  * certname is in the form [<tokenname>:]<certnickname>
1660  * where <tokenname> is the name of the PKCS11 token
1661  * and <certnickname> is the nickname of the cert/key in
1662  * the database
1663 */
1664 static int
1665 tlsm_clientauth_init( tlsm_ctx *ctx )
1666 {
1667         SECStatus status = SECFailure;
1668         int rc;
1669
1670         rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
1671         if ( rc ) {
1672                 Debug( LDAP_DEBUG_ANY,
1673                            "TLS: error: unable to set up client certificate authentication for "
1674                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1675                 return -1;
1676         }
1677
1678         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1679                                                                                 tlsm_get_client_auth_data,
1680                                                                                 (void *)ctx );
1681
1682         return ( status == SECSuccess ? 0 : -1 );
1683 }
1684
1685 /*
1686  * Tear down the TLS subsystem. Should only be called once.
1687  */
1688 static void
1689 tlsm_destroy( void )
1690 {
1691 }
1692
1693 static tls_ctx *
1694 tlsm_ctx_new ( struct ldapoptions *lo )
1695 {
1696         tlsm_ctx *ctx;
1697
1698         ctx = LDAP_MALLOC( sizeof (*ctx) );
1699         if ( ctx ) {
1700                 ctx->tc_refcnt = 1;
1701 #ifdef LDAP_R_COMPILE
1702                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
1703 #endif
1704                 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 */
1705                 ctx->tc_certdb = NULL;
1706                 ctx->tc_certname = NULL;
1707                 ctx->tc_pin_file = NULL;
1708                 ctx->tc_model = NULL;
1709                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
1710                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
1711                 ctx->tc_verify_cert = PR_FALSE;
1712                 ctx->tc_using_pem = PR_FALSE;
1713                 ctx->tc_slotname = NULL;
1714 #ifdef HAVE_NSS_INITCONTEXT
1715                 ctx->tc_initctx = NULL;
1716 #endif /* HAVE_NSS_INITCONTEXT */
1717                 ctx->tc_pem_objs = NULL;
1718                 ctx->tc_n_pem_objs = 0;
1719         }
1720         return (tls_ctx *)ctx;
1721 }
1722
1723 static void
1724 tlsm_ctx_ref( tls_ctx *ctx )
1725 {
1726         tlsm_ctx *c = (tlsm_ctx *)ctx;
1727 #ifdef LDAP_R_COMPILE
1728         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1729 #endif
1730         c->tc_refcnt++;
1731 #ifdef LDAP_R_COMPILE
1732         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1733 #endif
1734 }
1735
1736 static void
1737 tlsm_ctx_free ( tls_ctx *ctx )
1738 {
1739         tlsm_ctx *c = (tlsm_ctx *)ctx;
1740         int refcount;
1741
1742         if ( !c ) return;
1743
1744 #ifdef LDAP_R_COMPILE
1745         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1746 #endif
1747         refcount = --c->tc_refcnt;
1748 #ifdef LDAP_R_COMPILE
1749         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1750 #endif
1751         if ( refcount )
1752                 return;
1753         if ( c->tc_model )
1754                 PR_Close( c->tc_model );
1755         c->tc_certdb = NULL; /* if not the default, may have to clean up */
1756         PL_strfree( c->tc_certname );
1757         c->tc_certname = NULL;
1758         PL_strfree( c->tc_pin_file );
1759         c->tc_pin_file = NULL;
1760         PL_strfree( c->tc_slotname );           
1761         tlsm_free_pem_objs( c );
1762 #ifdef HAVE_NSS_INITCONTEXT
1763         if (c->tc_initctx)
1764                 NSS_ShutdownContext( c->tc_initctx );
1765         c->tc_initctx = NULL;
1766 #endif /* HAVE_NSS_INITCONTEXT */
1767 #ifdef LDAP_R_COMPILE
1768         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
1769 #endif
1770         LDAP_FREE( c );
1771 }
1772
1773 /*
1774  * initialize a new TLS context
1775  */
1776 static int
1777 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
1778 {
1779         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
1780         ctx->tc_is_server = is_server;
1781
1782         return 0;
1783 }
1784
1785 static int
1786 tlsm_deferred_ctx_init( void *arg )
1787 {
1788         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1789         PRBool sslv2 = PR_FALSE;
1790         PRBool sslv3 = PR_TRUE;
1791         PRBool tlsv1 = PR_TRUE;
1792         PRBool request_cert = PR_FALSE;
1793         PRInt32 require_cert = PR_FALSE;
1794         PRFileDesc *fd;
1795         struct ldaptls *lt;
1796
1797         if ( tlsm_deferred_init( ctx ) ) {
1798             Debug( LDAP_DEBUG_ANY,
1799                            "TLS: could perform TLS system initialization.\n",
1800                            0, 0, 0 );
1801             return -1;
1802         }
1803
1804         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
1805
1806         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
1807         if ( fd ) {
1808                 ctx->tc_model = SSL_ImportFD( NULL, fd );
1809         }
1810
1811         if ( !ctx->tc_model ) {
1812                 PRErrorCode err = PR_GetError();
1813                 Debug( LDAP_DEBUG_ANY,
1814                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
1815                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1816
1817                 if ( fd ) {
1818                         PR_Close( fd );
1819                 }
1820                 return -1;
1821         }
1822
1823         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
1824                 Debug( LDAP_DEBUG_ANY,
1825                        "TLS: could not set secure mode on.\n",
1826                        0, 0, 0 );
1827                 return -1;
1828         }
1829
1830         lt = ctx->tc_config;
1831
1832         /* default is sslv3 and tlsv1 */
1833         if ( lt->lt_protocol_min ) {
1834                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
1835                         sslv3 = PR_FALSE;
1836                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
1837                         sslv2 = PR_TRUE;
1838                         Debug( LDAP_DEBUG_ANY,
1839                                "TLS: warning: minimum TLS protocol level set to "
1840                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
1841                 }
1842         }
1843         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
1844                 Debug( LDAP_DEBUG_ANY,
1845                        "TLS: could not set SSLv2 mode on.\n",
1846                        0, 0, 0 );
1847                 return -1;
1848         }
1849         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
1850                 Debug( LDAP_DEBUG_ANY,
1851                        "TLS: could not set SSLv3 mode on.\n",
1852                        0, 0, 0 );
1853                 return -1;
1854         }
1855         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
1856                 Debug( LDAP_DEBUG_ANY,
1857                        "TLS: could not set TLSv1 mode on.\n",
1858                        0, 0, 0 );
1859                 return -1;
1860         }
1861
1862         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
1863                 Debug( LDAP_DEBUG_ANY,
1864                        "TLS: could not set handshake as client.\n",
1865                        0, 0, 0 );
1866                 return -1;
1867         }
1868         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
1869                 Debug( LDAP_DEBUG_ANY,
1870                        "TLS: could not set handshake as server.\n",
1871                        0, 0, 0 );
1872                 return -1;
1873         }
1874
1875         if ( lt->lt_ciphersuite &&
1876              tlsm_parse_ciphers( ctx, lt->lt_ciphersuite )) {
1877                 Debug( LDAP_DEBUG_ANY,
1878                        "TLS: could not set cipher list %s.\n",
1879                        lt->lt_ciphersuite, 0, 0 );
1880                 return -1;
1881         }
1882
1883         if ( ctx->tc_require_cert ) {
1884                 request_cert = PR_TRUE;
1885                 require_cert = SSL_REQUIRE_NO_ERROR;
1886                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
1887                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
1888                         require_cert = SSL_REQUIRE_ALWAYS;
1889                 }
1890                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
1891                         ctx->tc_verify_cert = PR_TRUE;
1892         } else {
1893                 ctx->tc_verify_cert = PR_FALSE;
1894         }
1895
1896         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
1897                 Debug( LDAP_DEBUG_ANY,
1898                        "TLS: could not set request certificate mode.\n",
1899                        0, 0, 0 );
1900                 return -1;
1901         }
1902                 
1903         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
1904                 Debug( LDAP_DEBUG_ANY,
1905                        "TLS: could not set require certificate mode.\n",
1906                        0, 0, 0 );
1907                 return -1;
1908         }
1909
1910         /* set up our cert and key, if any */
1911         if ( lt->lt_certfile ) {
1912                 /* if using the PEM module, load the PEM file specified by lt_certfile */
1913                 /* otherwise, assume this is the name of a cert already in the db */
1914                 if ( ctx->tc_using_pem ) {
1915                         /* this sets ctx->tc_certname to the correct value */
1916                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE /* not a ca */ );
1917                         if ( rc ) {
1918                                 return rc;
1919                         }
1920                 } else {
1921                         PL_strfree( ctx->tc_certname );
1922                         ctx->tc_certname = PL_strdup( lt->lt_certfile );
1923                 }
1924         }
1925
1926         if ( lt->lt_keyfile ) {
1927                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
1928                 /* otherwise, assume this is the pininfo for the key */
1929                 if ( ctx->tc_using_pem ) {
1930                         /* this sets ctx->tc_certname to the correct value */
1931                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
1932                         if ( rc ) {
1933                                 return rc;
1934                         }
1935                 } else {
1936                         PL_strfree( ctx->tc_pin_file );
1937                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
1938                 }
1939         }
1940
1941         /* Set up callbacks for use by clients */
1942         if ( !ctx->tc_is_server ) {
1943                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
1944                         PRErrorCode err = PR_GetError();
1945                         Debug( LDAP_DEBUG_ANY, 
1946                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
1947                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1948                         return -1;
1949                 }
1950
1951                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
1952                         PRErrorCode err = PR_GetError();
1953                         Debug( LDAP_DEBUG_ANY, 
1954                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
1955                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1956                         return -1;
1957                 }
1958
1959                 /* 
1960                    since a cert has been specified, assume the client wants to do cert auth
1961                 */
1962                 if ( ctx->tc_certname ) {
1963                         if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
1964                                 Debug( LDAP_DEBUG_ANY, 
1965                                        "TLS: error: unable to authenticate to the security device for certificate %s\n",
1966                                        ctx->tc_certname, 0, 0 );
1967                                 return -1;
1968                         }
1969                         if ( tlsm_clientauth_init( ctx ) ) {
1970                                 Debug( LDAP_DEBUG_ANY, 
1971                                        "TLS: error: unable to set up client certificate authentication using %s\n",
1972                                        ctx->tc_certname, 0, 0 );
1973                                 return -1;
1974                         }
1975                 }
1976         } else { /* set up secure server */
1977                 SSLKEAType certKEA;
1978                 CERTCertificate *serverCert;
1979                 SECKEYPrivateKey *serverKey;
1980                 SECStatus status;
1981
1982                 /* must have a certificate for the server to use */
1983                 if ( !ctx->tc_certname ) {
1984                         Debug( LDAP_DEBUG_ANY, 
1985                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
1986                                0, 0, 0 );
1987                         return -1;
1988                 }
1989
1990                 /* authenticate to the server's token - this will do nothing
1991                    if the key/cert db is not password protected */
1992                 if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
1993                         Debug( LDAP_DEBUG_ANY, 
1994                                "TLS: error: unable to authenticate to the security device for certificate %s\n",
1995                                ctx->tc_certname, 0, 0 );
1996                         return -1;
1997                 }
1998
1999                 /* get the server's key and cert */
2000                 if ( tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, ctx->tc_is_server,
2001                                                     &serverCert, &serverKey ) ) {
2002                         Debug( LDAP_DEBUG_ANY, 
2003                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2004                                ctx->tc_certname, 0, 0 );
2005                         return -1;
2006                 }
2007
2008                 certKEA = NSS_FindCertKEAType( serverCert );
2009                 /* configure the socket to be a secure server socket */
2010                 status = SSL_ConfigSecureServer( ctx->tc_model, serverCert, serverKey, certKEA );
2011                 /* SSL_ConfigSecureServer copies these */
2012                 CERT_DestroyCertificate( serverCert );
2013                 SECKEY_DestroyPrivateKey( serverKey );
2014
2015                 if ( SECSuccess != status ) {
2016                         PRErrorCode err = PR_GetError();
2017                         Debug( LDAP_DEBUG_ANY, 
2018                                "TLS: error: unable to configure secure server using certificate %s - error %d:%s\n",
2019                                ctx->tc_certname, err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2020                         return -1;
2021                 }
2022         }
2023
2024         /* Callback for authenticating certificate */
2025         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2026                                   ctx->tc_certdb ) != SECSuccess ) {
2027                 PRErrorCode err = PR_GetError();
2028                 Debug( LDAP_DEBUG_ANY, 
2029                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2030                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2031                 return -1;
2032         }
2033
2034         return 0;
2035 }
2036
2037 struct tls_data {
2038         tlsm_session            *session;
2039         Sockbuf_IO_Desc         *sbiod;
2040         /* there seems to be no portable way to determine if the
2041            sockbuf sd has been set to nonblocking mode - the
2042            call to ber_pvt_socket_set_nonblock() takes place
2043            before the tls socket is set up, so we cannot
2044            intercept that call either.
2045            On systems where fcntl is available, we can just
2046            F_GETFL and test for O_NONBLOCK.  On other systems,
2047            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2048            and just set this flag */
2049         PRBool              nonblock;
2050 };
2051
2052 static int
2053 tlsm_is_io_ready( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags )
2054 {
2055         struct tls_data         *p;
2056         PRFileDesc *pollfd = NULL;
2057         PRFileDesc *myfd;
2058         PRPollDesc polldesc;
2059         int rc;
2060
2061         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2062
2063         if ( !myfd ) {
2064                 return 0;
2065         }
2066
2067         p = (struct tls_data *)myfd->secret;
2068
2069         if ( p == NULL || p->sbiod == NULL ) {
2070                 return 0;
2071         }
2072
2073         /* wrap the sockbuf fd with a NSPR FD created especially
2074            for use with polling, and only with polling */
2075         pollfd = PR_CreateSocketPollFd( p->sbiod->sbiod_sb->sb_fd );
2076         polldesc.fd = pollfd;
2077         polldesc.in_flags = in_flags;
2078         polldesc.out_flags = 0;
2079
2080         /* do the poll - no waiting, no blocking */
2081         rc = PR_Poll( &polldesc, 1, PR_INTERVAL_NO_WAIT );
2082
2083         /* unwrap the socket */
2084         PR_DestroySocketPollFd( pollfd );
2085
2086         /* rc will be either 1 if IO is ready, 0 if IO is not
2087            ready, or -1 if there was some error (and the caller
2088            should use PR_GetError() to figure out what */
2089         if (out_flags) {
2090                 *out_flags = polldesc.out_flags;
2091         }
2092         return rc;
2093 }
2094
2095 static tls_session *
2096 tlsm_session_new ( tls_ctx * ctx, int is_server )
2097 {
2098         tlsm_ctx *c = (tlsm_ctx *)ctx;
2099         tlsm_session *session;
2100         PRFileDesc *fd;
2101         PRStatus status;
2102
2103         c->tc_is_server = is_server;
2104         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2105         if ( PR_SUCCESS != status ) {
2106                 PRErrorCode err = PR_GetError();
2107                 Debug( LDAP_DEBUG_ANY, 
2108                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2109                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2110                 return NULL;
2111         }
2112
2113         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2114         if ( !fd ) {
2115                 return NULL;
2116         }
2117
2118         session = SSL_ImportFD( c->tc_model, fd );
2119         if ( !session ) {
2120                 PR_DELETE( fd );
2121                 return NULL;
2122         }
2123
2124         if ( is_server ) {
2125                 /* 0 means use the defaults here */
2126                 SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
2127         }
2128
2129         return (tls_session *)session;
2130
2131
2132 static int
2133 tlsm_session_accept( tls_session *session )
2134 {
2135         tlsm_session *s = (tlsm_session *)session;
2136         int rc;
2137         PRErrorCode err;
2138         int waitcounter = 0;
2139
2140         rc = SSL_ResetHandshake( s, PR_TRUE /* server */ );
2141         if (rc) {
2142                 err = PR_GetError();
2143                 Debug( LDAP_DEBUG_TRACE, 
2144                            "TLS: error: accept - reset handshake failure %d - error %d:%s\n",
2145                            rc, err,
2146                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2147         }
2148
2149         do {
2150                 PRInt32 filesReady;
2151                 PRInt16 in_flags;
2152                 PRInt16 out_flags;
2153
2154                 errno = 0;
2155                 rc = SSL_ForceHandshake( s );
2156                 if (rc == SECSuccess) {
2157                         rc = 0;
2158                         break; /* done */
2159                 }
2160                 err = PR_GetError();
2161                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2162                         waitcounter++;
2163                         in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
2164                         out_flags = 0;
2165                         errno = 0;
2166                         filesReady = tlsm_is_io_ready( s, in_flags, &out_flags );
2167                         if ( filesReady < 0 ) {
2168                                 err = PR_GetError();
2169                                 Debug( LDAP_DEBUG_ANY, 
2170                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
2171                                            errno, err,
2172                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2173                                 rc = -1;
2174                                 break; /* hard error */
2175                         } else if ( out_flags & PR_POLL_NVAL ) {
2176                                 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
2177                                 Debug( LDAP_DEBUG_ANY, 
2178                                            "TLS: error: accept failure - invalid socket\n",
2179                                            NULL, NULL, NULL );
2180                                 rc = -1;
2181                                 break;
2182                         } else if ( out_flags & PR_POLL_EXCEPT ) {
2183                                 err = PR_GetError();
2184                                 Debug( LDAP_DEBUG_ANY, 
2185                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
2186                                            errno, err,
2187                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2188                                 rc = -1;
2189                                 break; /* hard error */
2190                         }
2191                 } else { /* hard error */
2192                         err = PR_GetError();
2193                         Debug( LDAP_DEBUG_ANY, 
2194                                    "TLS: error: accept - force handshake failure: %d - error %d:%s\n",
2195                                    errno, err,
2196                                    err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2197                         rc = -1;
2198                         break; /* hard error */
2199                 }
2200         } while (rc == SECFailure);
2201
2202         Debug( LDAP_DEBUG_TRACE, 
2203                    "TLS: accept completed after %d waits\n", waitcounter, NULL, NULL );
2204
2205         return rc;
2206 }
2207
2208 static int
2209 tlsm_session_connect( LDAP *ld, tls_session *session )
2210 {
2211         tlsm_session *s = (tlsm_session *)session;
2212         int rc;
2213         PRErrorCode err;
2214
2215         rc = SSL_ResetHandshake( s, PR_FALSE /* server */ );
2216         if (rc) {
2217                 err = PR_GetError();
2218                 Debug( LDAP_DEBUG_TRACE, 
2219                            "TLS: error: connect - reset handshake failure %d - error %d:%s\n",
2220                            rc, err,
2221                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2222         }
2223
2224         rc = SSL_ForceHandshake( s );
2225         if (rc) {
2226                 err = PR_GetError();
2227                 Debug( LDAP_DEBUG_TRACE, 
2228                            "TLS: error: connect - force handshake failure %d - error %d:%s\n",
2229                            rc, err,
2230                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2231         }
2232
2233         return rc;
2234 }
2235
2236 static int
2237 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2238 {
2239         /* Should never happen */
2240         rc = PR_GetError();
2241
2242         if ( rc != PR_PENDING_INTERRUPT_ERROR && rc != PR_WOULD_BLOCK_ERROR )
2243                 return 0;
2244         return 0;
2245 }
2246
2247 static char *
2248 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2249 {
2250         int i;
2251
2252         rc = PR_GetError();
2253         i = PR_GetErrorTextLength();
2254         if ( i > len ) {
2255                 char *msg = LDAP_MALLOC( i+1 );
2256                 PR_GetErrorText( msg );
2257                 memcpy( buf, msg, len );
2258                 LDAP_FREE( msg );
2259         } else if ( i ) {
2260                 PR_GetErrorText( buf );
2261         }
2262
2263         return i ? buf : NULL;
2264 }
2265
2266 static int
2267 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2268 {
2269         tlsm_session *s = (tlsm_session *)session;
2270         CERTCertificate *cert;
2271
2272         cert = SSL_LocalCertificate( s );
2273         if (!cert) return LDAP_INVALID_CREDENTIALS;
2274
2275         der_dn->bv_val = (char *)cert->derSubject.data;
2276         der_dn->bv_len = cert->derSubject.len;
2277         CERT_DestroyCertificate( cert );
2278         return 0;
2279 }
2280
2281 static int
2282 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2283 {
2284         tlsm_session *s = (tlsm_session *)session;
2285         CERTCertificate *cert;
2286
2287         cert = SSL_PeerCertificate( s );
2288         if (!cert) return LDAP_INVALID_CREDENTIALS;
2289         
2290         der_dn->bv_val = (char *)cert->derSubject.data;
2291         der_dn->bv_len = cert->derSubject.len;
2292         CERT_DestroyCertificate( cert );
2293         return 0;
2294 }
2295
2296 /* what kind of hostname were we given? */
2297 #define IS_DNS  0
2298 #define IS_IP4  1
2299 #define IS_IP6  2
2300
2301 static int
2302 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2303 {
2304         tlsm_session *s = (tlsm_session *)session;
2305         CERTCertificate *cert;
2306         const char *name, *domain = NULL, *ptr;
2307         int ret, ntype = IS_DNS, nlen, dlen;
2308 #ifdef LDAP_PF_INET6
2309         struct in6_addr addr;
2310 #else
2311         struct in_addr addr;
2312 #endif
2313         SECItem altname;
2314         SECStatus rv;
2315
2316         if( ldap_int_hostname &&
2317                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2318         {
2319                 name = ldap_int_hostname;
2320         } else {
2321                 name = name_in;
2322         }
2323         nlen = strlen( name );
2324
2325         cert = SSL_PeerCertificate( s );
2326         if (!cert) {
2327                 Debug( LDAP_DEBUG_ANY,
2328                         "TLS: unable to get peer certificate.\n",
2329                         0, 0, 0 );
2330                 /* if this was a fatal condition, things would have
2331                  * aborted long before now.
2332                  */
2333                 return LDAP_SUCCESS;
2334         }
2335
2336 #ifdef LDAP_PF_INET6
2337         if (name[0] == '[' && strchr(name, ']')) {
2338                 char *n2 = ldap_strdup(name+1);
2339                 *strchr(n2, ']') = 0;
2340                 if (inet_pton(AF_INET6, n2, &addr))
2341                         ntype = IS_IP6;
2342                 LDAP_FREE(n2);
2343         } else 
2344 #endif
2345         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2346                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2347         }
2348         if (ntype == IS_DNS ) {
2349                 domain = strchr( name, '.' );
2350                 if ( domain )
2351                         dlen = nlen - ( domain - name );
2352         }
2353
2354         ret = LDAP_LOCAL_ERROR;
2355
2356         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2357                 &altname );
2358         if ( rv == SECSuccess && altname.data ) {
2359                 PRArenaPool *arena;
2360                 CERTGeneralName *names, *cur;
2361
2362                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2363                 if ( !arena ) {
2364                         ret = LDAP_NO_MEMORY;
2365                         goto fail;
2366                 }
2367
2368                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2369                 if ( !cur )
2370                         goto altfail;
2371
2372                 do {
2373                         char *host;
2374                         int hlen;
2375
2376                         /* ignore empty */
2377                         if ( !cur->name.other.len ) continue;
2378
2379                         host = (char *)cur->name.other.data;
2380                         hlen = cur->name.other.len;
2381
2382                         if ( cur->type == certDNSName ) {
2383                                 if ( ntype != IS_DNS )  continue;
2384
2385                                 /* is this an exact match? */
2386                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2387                                         ret = LDAP_SUCCESS;
2388                                         break;
2389                                 }
2390
2391                                 /* is this a wildcard match? */
2392                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2393                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2394                                         ret = LDAP_SUCCESS;
2395                                         break;
2396                                 }
2397                         } else if ( cur->type == certIPAddress ) {
2398                                 if ( ntype == IS_DNS )  continue;
2399                                 
2400 #ifdef LDAP_PF_INET6
2401                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2402                                         continue;
2403                                 } else
2404 #endif
2405                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2406                                         continue;
2407                                 }
2408                                 if (!memcmp(host, &addr, hlen)) {
2409                                         ret = LDAP_SUCCESS;
2410                                         break;
2411                                 }
2412                         }
2413                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2414 altfail:
2415                 PORT_FreeArena( arena, PR_FALSE );
2416                 SECITEM_FreeItem( &altname, PR_FALSE );
2417         }
2418         /* no altnames matched, try the CN */
2419         if ( ret != LDAP_SUCCESS ) {
2420                 /* find the last CN */
2421                 CERTRDN *rdn, **rdns;
2422                 CERTAVA *lastava = NULL;
2423                 char buf[2048];
2424
2425                 buf[0] = '\0';
2426                 rdns = cert->subject.rdns;
2427                 while ( rdns && ( rdn = *rdns++ )) {
2428                         CERTAVA *ava, **avas = rdn->avas;
2429                         while ( avas && ( ava = *avas++ )) {
2430                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2431                                         lastava = ava;
2432                         }
2433                 }
2434                 if ( lastava ) {
2435                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2436                         if ( av ) {
2437                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2438                                         ret = LDAP_SUCCESS;
2439                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2440                                         domain && dlen == av->len - 1 && !strncasecmp( name,
2441                                                 (char *)(av->data+1), dlen )) {
2442                                         ret = LDAP_SUCCESS;
2443                                 } else {
2444                                         int len = av->len;
2445                                         if ( len >= sizeof(buf) )
2446                                                 len = sizeof(buf)-1;
2447                                         memcpy( buf, av->data, len );
2448                                         buf[len] = '\0';
2449                                 }
2450                                 SECITEM_FreeItem( av, PR_TRUE );
2451                         }
2452                 }
2453                 if ( ret != LDAP_SUCCESS ) {
2454                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2455                                 "common name in certificate (%s).\n", 
2456                                 name, buf, 0 );
2457                         ret = LDAP_CONNECT_ERROR;
2458                         if ( ld->ld_error ) {
2459                                 LDAP_FREE( ld->ld_error );
2460                         }
2461                         ld->ld_error = LDAP_STRDUP(
2462                                 _("TLS: hostname does not match CN in peer certificate"));
2463                 }
2464         }
2465
2466 fail:
2467         CERT_DestroyCertificate( cert );
2468         return ret;
2469 }
2470
2471 static int
2472 tlsm_session_strength( tls_session *session )
2473 {
2474         tlsm_session *s = (tlsm_session *)session;
2475         int rc, keySize;
2476
2477         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2478                 NULL, NULL );
2479         return rc ? 0 : keySize;
2480 }
2481
2482 /*
2483  * TLS support for LBER Sockbufs
2484  */
2485
2486 static PRStatus PR_CALLBACK
2487 tlsm_PR_Close(PRFileDesc *fd)
2488 {
2489         int rc = PR_SUCCESS;
2490
2491         /* we don't need to actually close anything here, just
2492            pop our io layer off the stack */
2493         fd->secret = NULL; /* must have been freed before calling PR_Close */
2494         if ( fd->lower ) {
2495                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2496                 /* if we are not the last layer, pass the close along */
2497                 if ( fd ) {
2498                         if ( fd->dtor ) {
2499                                 fd->dtor( fd );
2500                         }
2501                         rc = fd->methods->close( fd );
2502                 }
2503         } else {
2504                 /* we are the last layer - just call our dtor */
2505                 fd->dtor(fd);
2506         }
2507
2508         return rc;
2509 }
2510
2511 static PRStatus PR_CALLBACK
2512 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2513 {
2514         int rc = PR_SUCCESS;
2515
2516         if ( fd->lower ) {
2517                 rc = PR_Shutdown( fd->lower, how );
2518         }
2519
2520         return rc;
2521 }
2522
2523 static int PR_CALLBACK
2524 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2525          PRIntervalTime timeout)
2526 {
2527         struct tls_data         *p;
2528         int rc;
2529
2530         if ( buf == NULL || len <= 0 ) return 0;
2531
2532         p = (struct tls_data *)fd->secret;
2533
2534         if ( p == NULL || p->sbiod == NULL ) {
2535                 return 0;
2536         }
2537
2538         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2539         if (rc <= 0) {
2540                 tlsm_map_error( errno );
2541                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2542                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2543                 } else if ( errno ) { /* real error */
2544                         Debug( LDAP_DEBUG_TRACE, 
2545                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2546                                rc, errno, STRERROR(errno) );
2547                 }
2548         }
2549
2550         return rc;
2551 }
2552
2553 static int PR_CALLBACK
2554 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2555          PRIntervalTime timeout)
2556 {
2557         struct tls_data         *p;
2558         int rc;
2559
2560         if ( buf == NULL || len <= 0 ) return 0;
2561
2562         p = (struct tls_data *)fd->secret;
2563
2564         if ( p == NULL || p->sbiod == NULL ) {
2565                 return 0;
2566         }
2567
2568         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
2569         if (rc <= 0) {
2570                 tlsm_map_error( errno );
2571                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2572                         p->nonblock = PR_TRUE;
2573                 } else if ( errno ) { /* real error */
2574                         Debug( LDAP_DEBUG_TRACE, 
2575                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
2576                                rc, errno, STRERROR(errno) );
2577                 }
2578         }
2579
2580         return rc;
2581 }
2582
2583 static int PR_CALLBACK
2584 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
2585 {
2586         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2587 }
2588
2589 static int PR_CALLBACK
2590 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
2591 {
2592         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2593 }
2594
2595 static PRStatus PR_CALLBACK
2596 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
2597 {
2598         struct tls_data         *p;
2599         ber_socklen_t len;
2600
2601         p = (struct tls_data *)fd->secret;
2602
2603         if ( p == NULL || p->sbiod == NULL ) {
2604                 return PR_FAILURE;
2605         }
2606         len = sizeof(PRNetAddr);
2607         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
2608 }
2609
2610 static PRStatus PR_CALLBACK
2611 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
2612 {
2613         struct tls_data         *p;
2614         p = (struct tls_data *)fd->secret;
2615
2616         if ( !data ) {
2617                 return PR_FAILURE;
2618         }
2619
2620         /* only the nonblocking option is supported at this time
2621            MozNSS SSL code needs it */
2622         if ( data->option != PR_SockOpt_Nonblocking ) {
2623                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2624                 return PR_FAILURE;
2625         }
2626 #ifdef HAVE_FCNTL
2627         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
2628         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
2629 #else /* punt :P */
2630         data->value.non_blocking = p->nonblock;
2631 #endif
2632         return PR_SUCCESS;
2633 }
2634
2635 static PRStatus PR_CALLBACK
2636 tlsm_PR_prs_unimp()
2637 {
2638     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2639     return PR_FAILURE;
2640 }
2641
2642 static PRFileDesc * PR_CALLBACK
2643 tlsm_PR_pfd_unimp()
2644 {
2645     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2646     return NULL;
2647 }
2648
2649 static PRInt16 PR_CALLBACK
2650 tlsm_PR_i16_unimp()
2651 {
2652     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2653     return SECFailure;
2654 }
2655
2656 static PRInt32 PR_CALLBACK
2657 tlsm_PR_i32_unimp()
2658 {
2659     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2660     return SECFailure;
2661 }
2662
2663 static PRInt64 PR_CALLBACK
2664 tlsm_PR_i64_unimp()
2665 {
2666     PRInt64 res;
2667
2668     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2669     LL_I2L(res, -1L);
2670     return res;
2671 }
2672
2673 static const PRIOMethods tlsm_PR_methods = {
2674     PR_DESC_LAYERED,
2675     tlsm_PR_Close,                      /* close        */
2676     tlsm_PR_Read,                       /* read         */
2677     tlsm_PR_Write,                      /* write        */
2678     tlsm_PR_i32_unimp,          /* available    */
2679     tlsm_PR_i64_unimp,          /* available64  */
2680     tlsm_PR_prs_unimp,          /* fsync        */
2681     tlsm_PR_i32_unimp,          /* seek         */
2682     tlsm_PR_i64_unimp,          /* seek64       */
2683     tlsm_PR_prs_unimp,          /* fileInfo     */
2684     tlsm_PR_prs_unimp,          /* fileInfo64   */
2685     tlsm_PR_i32_unimp,          /* writev       */
2686     tlsm_PR_prs_unimp,          /* connect      */
2687     tlsm_PR_pfd_unimp,          /* accept       */
2688     tlsm_PR_prs_unimp,          /* bind         */
2689     tlsm_PR_prs_unimp,          /* listen       */
2690     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
2691     tlsm_PR_Recv,                       /* recv         */
2692     tlsm_PR_Send,                       /* send         */
2693     tlsm_PR_i32_unimp,          /* recvfrom     */
2694     tlsm_PR_i32_unimp,          /* sendto       */
2695     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
2696     tlsm_PR_i32_unimp,          /* acceptread   */
2697     tlsm_PR_i32_unimp,          /* transmitfile */
2698     tlsm_PR_prs_unimp,          /* getsockname  */
2699     tlsm_PR_GetPeerName,        /* getpeername  */
2700     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
2701     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
2702     tlsm_PR_GetSocketOption,            /* getsocketoption   */
2703     tlsm_PR_i32_unimp,          /* setsocketoption   */
2704     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
2705     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
2706     tlsm_PR_i32_unimp,          /* reserved for future use */
2707     tlsm_PR_i32_unimp,          /* reserved for future use */
2708     tlsm_PR_i32_unimp,          /* reserved for future use */
2709     tlsm_PR_i32_unimp           /* reserved for future use */
2710 };
2711
2712 /*
2713  * Initialize TLS subsystem. Should be called only once.
2714  * See tlsm_deferred_init for the bulk of the init process
2715  */
2716 static int
2717 tlsm_init( void )
2718 {
2719         PR_Init(0, 0, 0);
2720
2721         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
2722
2723         return 0;
2724 }
2725
2726 static int
2727 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
2728 {
2729         struct tls_data         *p;
2730         tlsm_session    *session = arg;
2731         PRFileDesc *fd;
2732
2733         assert( sbiod != NULL );
2734
2735         p = LBER_MALLOC( sizeof( *p ) );
2736         if ( p == NULL ) {
2737                 return -1;
2738         }
2739
2740         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
2741         if ( !fd ) {
2742                 LBER_FREE( p );
2743                 return -1;
2744         }
2745
2746         fd->secret = (PRFilePrivate *)p;
2747         p->session = session;
2748         p->sbiod = sbiod;
2749         sbiod->sbiod_pvt = p;
2750         return 0;
2751 }
2752
2753 static int
2754 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
2755 {
2756         struct tls_data         *p;
2757         
2758         assert( sbiod != NULL );
2759         assert( sbiod->sbiod_pvt != NULL );
2760
2761         p = (struct tls_data *)sbiod->sbiod_pvt;
2762         PR_Close( p->session );
2763         LBER_FREE( sbiod->sbiod_pvt );
2764         sbiod->sbiod_pvt = NULL;
2765         return 0;
2766 }
2767
2768 static int
2769 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
2770 {
2771         struct tls_data         *p;
2772         
2773         assert( sbiod != NULL );
2774         assert( sbiod->sbiod_pvt != NULL );
2775
2776         p = (struct tls_data *)sbiod->sbiod_pvt;
2777         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
2778         return 0;
2779 }
2780
2781 static int
2782 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
2783 {
2784         struct tls_data         *p;
2785         
2786         assert( sbiod != NULL );
2787         assert( sbiod->sbiod_pvt != NULL );
2788
2789         p = (struct tls_data *)sbiod->sbiod_pvt;
2790         
2791         if ( opt == LBER_SB_OPT_GET_SSL ) {
2792                 *((tlsm_session **)arg) = p->session;
2793                 return 1;
2794                 
2795         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
2796                 if ( tlsm_is_io_ready( p->session, PR_POLL_READ, NULL ) > 0 ) {
2797                         return 1;
2798                 }
2799                 
2800         }
2801         
2802         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
2803 }
2804
2805 static ber_slen_t
2806 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2807 {
2808         struct tls_data         *p;
2809         ber_slen_t              ret;
2810         int                     err;
2811
2812         assert( sbiod != NULL );
2813         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2814
2815         p = (struct tls_data *)sbiod->sbiod_pvt;
2816
2817         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2818         if ( ret < 0 ) {
2819                 err = PR_GetError();
2820                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2821                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
2822                         sock_errset(EWOULDBLOCK);
2823                 }
2824         } else {
2825                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
2826         }
2827         return ret;
2828 }
2829
2830 static ber_slen_t
2831 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2832 {
2833         struct tls_data         *p;
2834         ber_slen_t              ret;
2835         int                     err;
2836
2837         assert( sbiod != NULL );
2838         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2839
2840         p = (struct tls_data *)sbiod->sbiod_pvt;
2841
2842         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2843         if ( ret < 0 ) {
2844                 err = PR_GetError();
2845                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2846                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
2847                         sock_errset(EWOULDBLOCK);
2848                         ret = 0;
2849                 }
2850         } else {
2851                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
2852         }
2853         return ret;
2854 }
2855
2856 static Sockbuf_IO tlsm_sbio =
2857 {
2858         tlsm_sb_setup,          /* sbi_setup */
2859         tlsm_sb_remove,         /* sbi_remove */
2860         tlsm_sb_ctrl,           /* sbi_ctrl */
2861         tlsm_sb_read,           /* sbi_read */
2862         tlsm_sb_write,          /* sbi_write */
2863         tlsm_sb_close           /* sbi_close */
2864 };
2865
2866 tls_impl ldap_int_tls_impl = {
2867         "MozNSS",
2868
2869         tlsm_init,
2870         tlsm_destroy,
2871
2872         tlsm_ctx_new,
2873         tlsm_ctx_ref,
2874         tlsm_ctx_free,
2875         tlsm_ctx_init,
2876
2877         tlsm_session_new,
2878         tlsm_session_connect,
2879         tlsm_session_accept,
2880         tlsm_session_upflags,
2881         tlsm_session_errmsg,
2882         tlsm_session_my_dn,
2883         tlsm_session_peer_dn,
2884         tlsm_session_chkhost,
2885         tlsm_session_strength,
2886
2887         &tlsm_sbio,
2888
2889 #ifdef LDAP_R_COMPILE
2890         tlsm_thr_init,
2891 #else
2892         NULL,
2893 #endif
2894
2895         0
2896 };
2897
2898 #endif /* HAVE_MOZNSS */
2899 /*
2900   emacs settings
2901   Local Variables:
2902   indent-tabs-mode: t
2903   tab-width: 4
2904   End:
2905 */