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