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