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