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