xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/tls2.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: tls2.c,v 1.1.1.1 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* tls.c - Handle tls/ssl. */
4 /* OpenLDAP: pkg/ldap/libraries/libldap/tls2.c,v 1.4.2.9 2009/10/30 17:48:16 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2009 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS: restructured by Howard Chu.
19  */
20 
21 #include "portable.h"
22 #include "ldap_config.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/stdlib.h>
27 #include <ac/errno.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/ctype.h>
31 #include <ac/time.h>
32 #include <ac/unistd.h>
33 #include <ac/param.h>
34 #include <ac/dirent.h>
35 
36 #include "ldap-int.h"
37 
38 #ifdef HAVE_TLS
39 
40 #include "ldap-tls.h"
41 
42 #ifdef LDAP_R_COMPILE
43 #include <ldap_pvt_thread.h>
44 #endif
45 
46 static tls_impl *tls_imp = &ldap_int_tls_impl;
47 #define HAS_TLS( sb )	ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
48 				(void *)tls_imp->ti_sbio )
49 
50 #endif /* HAVE_TLS */
51 
52 /* RFC2459 minimum required set of supported attribute types
53  * in a certificate DN
54  */
55 typedef struct oid_name {
56 	struct berval oid;
57 	struct berval name;
58 } oid_name;
59 
60 static oid_name oids[] = {
61 	{ BER_BVC("2.5.4.3"), BER_BVC("cn") },
62 	{ BER_BVC("2.5.4.4"), BER_BVC("sn") },
63 	{ BER_BVC("2.5.4.6"), BER_BVC("c") },
64 	{ BER_BVC("2.5.4.7"), BER_BVC("l") },
65 	{ BER_BVC("2.5.4.8"), BER_BVC("st") },
66 	{ BER_BVC("2.5.4.10"), BER_BVC("o") },
67 	{ BER_BVC("2.5.4.11"), BER_BVC("ou") },
68 	{ BER_BVC("2.5.4.12"), BER_BVC("title") },
69 	{ BER_BVC("2.5.4.41"), BER_BVC("name") },
70 	{ BER_BVC("2.5.4.42"), BER_BVC("givenName") },
71 	{ BER_BVC("2.5.4.43"), BER_BVC("initials") },
72 	{ BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") },
73 	{ BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") },
74 	{ BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") },
75 	{ BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") },
76 	{ BER_BVNULL, BER_BVNULL }
77 };
78 
79 #ifdef HAVE_TLS
80 
81 void
82 ldap_pvt_tls_ctx_free ( void *c )
83 {
84 	if ( !c ) return;
85 	tls_imp->ti_ctx_free( c );
86 }
87 
88 static void
89 tls_ctx_ref( tls_ctx *ctx )
90 {
91 	if ( !ctx ) return;
92 
93 	tls_imp->ti_ctx_ref( ctx );
94 }
95 
96 #ifdef LDAP_R_COMPILE
97 /*
98  * an extra mutex for the default ctx.
99  */
100 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
101 #endif
102 
103 void
104 ldap_int_tls_destroy( struct ldapoptions *lo )
105 {
106 	if ( lo->ldo_tls_ctx ) {
107 		ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
108 		lo->ldo_tls_ctx = NULL;
109 	}
110 
111 	if ( lo->ldo_tls_certfile ) {
112 		LDAP_FREE( lo->ldo_tls_certfile );
113 		lo->ldo_tls_certfile = NULL;
114 	}
115 	if ( lo->ldo_tls_keyfile ) {
116 		LDAP_FREE( lo->ldo_tls_keyfile );
117 		lo->ldo_tls_keyfile = NULL;
118 	}
119 	if ( lo->ldo_tls_dhfile ) {
120 		LDAP_FREE( lo->ldo_tls_dhfile );
121 		lo->ldo_tls_dhfile = NULL;
122 	}
123 	if ( lo->ldo_tls_cacertfile ) {
124 		LDAP_FREE( lo->ldo_tls_cacertfile );
125 		lo->ldo_tls_cacertfile = NULL;
126 	}
127 	if ( lo->ldo_tls_cacertdir ) {
128 		LDAP_FREE( lo->ldo_tls_cacertdir );
129 		lo->ldo_tls_cacertdir = NULL;
130 	}
131 	if ( lo->ldo_tls_ciphersuite ) {
132 		LDAP_FREE( lo->ldo_tls_ciphersuite );
133 		lo->ldo_tls_ciphersuite = NULL;
134 	}
135 	if ( lo->ldo_tls_crlfile ) {
136 		LDAP_FREE( lo->ldo_tls_crlfile );
137 		lo->ldo_tls_crlfile = NULL;
138 	}
139 }
140 
141 /*
142  * Tear down the TLS subsystem. Should only be called once.
143  */
144 void
145 ldap_pvt_tls_destroy( void )
146 {
147 	struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
148 
149 	ldap_int_tls_destroy( lo );
150 
151 	tls_imp->ti_tls_destroy();
152 }
153 
154 /*
155  * Initialize a particular TLS implementation.
156  * Called once per implementation.
157  */
158 static int
159 tls_init(tls_impl *impl )
160 {
161 	static int tls_initialized = 0;
162 
163 	if ( !tls_initialized++ ) {
164 #ifdef LDAP_R_COMPILE
165 		ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
166 #endif
167 	}
168 
169 	if ( impl->ti_inited++ ) return 0;
170 
171 #ifdef LDAP_R_COMPILE
172 	impl->ti_thr_init();
173 #endif
174 	return impl->ti_tls_init();
175 }
176 
177 /*
178  * Initialize TLS subsystem. Called once per implementation.
179  */
180 int
181 ldap_pvt_tls_init( void )
182 {
183 	return tls_init( tls_imp );
184 }
185 
186 /*
187  * initialize a new TLS context
188  */
189 static int
190 ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
191 {
192 	int rc = 0;
193 	tls_impl *ti = tls_imp;
194 	struct ldaptls lts = lo->ldo_tls_info;
195 
196 	if ( lo->ldo_tls_ctx )
197 		return 0;
198 
199 	tls_init( ti );
200 
201 	if ( is_server && !lts.lt_certfile && !lts.lt_keyfile &&
202 		!lts.lt_cacertfile && !lts.lt_cacertdir ) {
203 		/* minimum configuration not provided */
204 		return LDAP_NOT_SUPPORTED;
205 	}
206 
207 #ifdef HAVE_EBCDIC
208 	/* This ASCII/EBCDIC handling is a real pain! */
209 	if ( lts.lt_ciphersuite ) {
210 		lts.lt_ciphersuite = LDAP_STRDUP( lts.lt_ciphersuite );
211 		__atoe( lts.lt_ciphersuite );
212 	}
213 	if ( lts.lt_cacertfile ) {
214 		lts.lt_cacertfile = LDAP_STRDUP( lts.lt_cacertfile );
215 		__atoe( lts.lt_cacertfile );
216 	}
217 	if ( lts.lt_certfile ) {
218 		lts.lt_certfile = LDAP_STRDUP( lts.lt_certfile );
219 		__atoe( lts.lt_certfile );
220 	}
221 	if ( lts.lt_keyfile ) {
222 		lts.lt_keyfile = LDAP_STRDUP( lts.lt_keyfile );
223 		__atoe( lts.lt_keyfile );
224 	}
225 	if ( lts.lt_crlfile ) {
226 		lts.lt_crlfile = LDAP_STRDUP( lts.lt_crlfile );
227 		__atoe( lts.lt_crlfile );
228 	}
229 	if ( lts.lt_cacertdir ) {
230 		lts.lt_cacertdir = LDAP_STRDUP( lts.lt_cacertdir );
231 		__atoe( lts.lt_cacertdir );
232 	}
233 	if ( lts.lt_dhfile ) {
234 		lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile );
235 		__atoe( lts.lt_dhfile );
236 	}
237 #endif
238 	lo->ldo_tls_ctx = ti->ti_ctx_new( lo );
239 	if ( lo->ldo_tls_ctx == NULL ) {
240 		Debug( LDAP_DEBUG_ANY,
241 		   "TLS: could not allocate default ctx.\n",
242 			0,0,0);
243 		rc = -1;
244 		goto error_exit;
245 	}
246 
247 	rc = ti->ti_ctx_init( lo, &lts, is_server );
248 
249 error_exit:
250 	if ( rc < 0 && lo->ldo_tls_ctx != NULL ) {
251 		ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
252 		lo->ldo_tls_ctx = NULL;
253 	}
254 #ifdef HAVE_EBCDIC
255 	LDAP_FREE( lts.lt_ciphersuite );
256 	LDAP_FREE( lts.lt_cacertfile );
257 	LDAP_FREE( lts.lt_certfile );
258 	LDAP_FREE( lts.lt_keyfile );
259 	LDAP_FREE( lts.lt_crlfile );
260 	LDAP_FREE( lts.lt_cacertdir );
261 	LDAP_FREE( lts.lt_dhfile );
262 #endif
263 	return rc;
264 }
265 
266 /*
267  * initialize the default context
268  */
269 int
270 ldap_pvt_tls_init_def_ctx( int is_server )
271 {
272 	struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
273 	int rc;
274 #ifdef LDAP_R_COMPILE
275 	ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex );
276 #endif
277 	rc = ldap_int_tls_init_ctx( lo, is_server );
278 #ifdef LDAP_R_COMPILE
279 	ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex );
280 #endif
281 	return rc;
282 }
283 
284 static tls_session *
285 alloc_handle( void *ctx_arg, int is_server )
286 {
287 	tls_ctx	*ctx;
288 	tls_session	*ssl;
289 
290 	if ( ctx_arg ) {
291 		ctx = ctx_arg;
292 	} else {
293 		struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
294 		if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL;
295 		ctx = lo->ldo_tls_ctx;
296 	}
297 
298 	ssl = tls_imp->ti_session_new( ctx, is_server );
299 	if ( ssl == NULL ) {
300 		Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
301 		return NULL;
302 	}
303 	return ssl;
304 }
305 
306 static int
307 update_flags( Sockbuf *sb, tls_session * ssl, int rc )
308 {
309 	sb->sb_trans_needs_read  = 0;
310 	sb->sb_trans_needs_write = 0;
311 
312 	return tls_imp->ti_session_upflags( sb, ssl, rc );
313 }
314 
315 /*
316  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
317  * a SSL_CTX * or NULL, in which case the default ctx is used.
318  *
319  * Return value:
320  *
321  *  0 - Success. Connection is ready for communication.
322  * <0 - Error. Can't create a TLS stream.
323  * >0 - Partial success.
324  *	  Do a select (using information from lber_pvt_sb_needs_{read,write}
325  *		and call again.
326  */
327 
328 static int
329 ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
330 {
331 	Sockbuf *sb = conn->lconn_sb;
332 	int	err;
333 	tls_session	*ssl = NULL;
334 
335 	if ( HAS_TLS( sb )) {
336 		ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
337 	} else {
338 		struct ldapoptions *lo;
339 		tls_ctx *ctx;
340 
341 		ctx = ld->ld_options.ldo_tls_ctx;
342 
343 		ssl = alloc_handle( ctx, 0 );
344 
345 		if ( ssl == NULL ) return -1;
346 
347 #ifdef LDAP_DEBUG
348 		ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
349 			LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
350 #endif
351 		ber_sockbuf_add_io( sb, tls_imp->ti_sbio,
352 			LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
353 
354 		lo = LDAP_INT_GLOBAL_OPT();
355 		if( ctx == NULL ) {
356 			ctx = lo->ldo_tls_ctx;
357 			ld->ld_options.ldo_tls_ctx = ctx;
358 			tls_ctx_ref( ctx );
359 		}
360 		if ( ld->ld_options.ldo_tls_connect_cb )
361 			ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx,
362 			ld->ld_options.ldo_tls_connect_arg );
363 		if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb !=
364 			ld->ld_options.ldo_tls_connect_cb )
365 			lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
366 	}
367 
368 	err = tls_imp->ti_session_connect( ld, ssl );
369 
370 #ifdef HAVE_WINSOCK
371 	errno = WSAGetLastError();
372 #endif
373 
374 	if ( err < 0 )
375 	{
376 		char buf[256], *msg;
377 		if ( update_flags( sb, ssl, err )) {
378 			return 1;
379 		}
380 
381 		msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) );
382 		if ( msg ) {
383 			if ( ld->ld_error ) {
384 				LDAP_FREE( ld->ld_error );
385 			}
386 			ld->ld_error = LDAP_STRDUP( msg );
387 #ifdef HAVE_EBCDIC
388 			if ( ld->ld_error ) __etoa(ld->ld_error);
389 #endif
390 		}
391 
392 		Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n",
393 			ld->ld_error ? ld->ld_error : "" ,0,0);
394 
395 		ber_sockbuf_remove_io( sb, tls_imp->ti_sbio,
396 			LBER_SBIOD_LEVEL_TRANSPORT );
397 #ifdef LDAP_DEBUG
398 		ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
399 			LBER_SBIOD_LEVEL_TRANSPORT );
400 #endif
401 		return -1;
402 	}
403 
404 	return 0;
405 }
406 
407 /*
408  * Call this to do a TLS accept on a sockbuf.
409  * Everything else is the same as with tls_connect.
410  */
411 int
412 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
413 {
414 	int	err;
415 	tls_session	*ssl = NULL;
416 
417 	if ( HAS_TLS( sb )) {
418 		ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
419 	} else {
420 		ssl = alloc_handle( ctx_arg, 1 );
421 		if ( ssl == NULL ) return -1;
422 
423 #ifdef LDAP_DEBUG
424 		ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
425 			LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
426 #endif
427 		ber_sockbuf_add_io( sb, tls_imp->ti_sbio,
428 			LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
429 	}
430 
431 	err = tls_imp->ti_session_accept( ssl );
432 
433 #ifdef HAVE_WINSOCK
434 	errno = WSAGetLastError();
435 #endif
436 
437 	if ( err < 0 )
438 	{
439 		if ( update_flags( sb, ssl, err )) return 1;
440 
441 		if ( DebugTest( LDAP_DEBUG_ANY ) ) {
442 			char buf[256], *msg;
443 			msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) );
444 			Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n",
445 				msg ? msg : "(unknown)", 0, 0 );
446 		}
447 
448 		ber_sockbuf_remove_io( sb, tls_imp->ti_sbio,
449 			LBER_SBIOD_LEVEL_TRANSPORT );
450 #ifdef LDAP_DEBUG
451 		ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
452 			LBER_SBIOD_LEVEL_TRANSPORT );
453 #endif
454 		return -1;
455 	}
456 	return 0;
457 }
458 
459 int
460 ldap_pvt_tls_inplace ( Sockbuf *sb )
461 {
462 	return HAS_TLS( sb ) ? 1 : 0;
463 }
464 
465 int
466 ldap_tls_inplace( LDAP *ld )
467 {
468 	Sockbuf		*sb = NULL;
469 
470 	if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) {
471 		sb = ld->ld_defconn->lconn_sb;
472 
473 	} else if ( ld->ld_sb ) {
474 		sb = ld->ld_sb;
475 
476 	} else {
477 		return 0;
478 	}
479 
480 	return ldap_pvt_tls_inplace( sb );
481 }
482 
483 int
484 ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn,
485 	LDAPDN_rewrite_dummy *func, unsigned flags )
486 {
487 	tls_session *session = s;
488 	struct berval bvdn;
489 	int rc;
490 
491 	rc = tls_imp->ti_session_peer_dn( session, &bvdn );
492 	if ( rc ) return rc;
493 
494 	rc = ldap_X509dn2bv( &bvdn, dn,
495 			    (LDAPDN_rewrite_func *)func, flags);
496 	return rc;
497 }
498 
499 int
500 ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
501 {
502 	tls_session *session = s;
503 
504 	return tls_imp->ti_session_chkhost( ld, session, name_in );
505 }
506 
507 int
508 ldap_int_tls_config( LDAP *ld, int option, const char *arg )
509 {
510 	int i;
511 
512 	switch( option ) {
513 	case LDAP_OPT_X_TLS_CACERTFILE:
514 	case LDAP_OPT_X_TLS_CACERTDIR:
515 	case LDAP_OPT_X_TLS_CERTFILE:
516 	case LDAP_OPT_X_TLS_KEYFILE:
517 	case LDAP_OPT_X_TLS_RANDOM_FILE:
518 	case LDAP_OPT_X_TLS_CIPHER_SUITE:
519 	case LDAP_OPT_X_TLS_DHFILE:
520 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
521 		return ldap_pvt_tls_set_option( ld, option, (void *) arg );
522 
523 	case LDAP_OPT_X_TLS_REQUIRE_CERT:
524 	case LDAP_OPT_X_TLS:
525 		i = -1;
526 		if ( strcasecmp( arg, "never" ) == 0 ) {
527 			i = LDAP_OPT_X_TLS_NEVER ;
528 
529 		} else if ( strcasecmp( arg, "demand" ) == 0 ) {
530 			i = LDAP_OPT_X_TLS_DEMAND ;
531 
532 		} else if ( strcasecmp( arg, "allow" ) == 0 ) {
533 			i = LDAP_OPT_X_TLS_ALLOW ;
534 
535 		} else if ( strcasecmp( arg, "try" ) == 0 ) {
536 			i = LDAP_OPT_X_TLS_TRY ;
537 
538 		} else if ( ( strcasecmp( arg, "hard" ) == 0 ) ||
539 			( strcasecmp( arg, "on" ) == 0 ) ||
540 			( strcasecmp( arg, "yes" ) == 0) ||
541 			( strcasecmp( arg, "true" ) == 0 ) )
542 		{
543 			i = LDAP_OPT_X_TLS_HARD ;
544 		}
545 
546 		if (i >= 0) {
547 			return ldap_pvt_tls_set_option( ld, option, &i );
548 		}
549 		return -1;
550 	case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
551 		char *next;
552 		long l;
553 		l = strtol( arg, &next, 10 );
554 		if ( l < 0 || l > 0xff || next == arg ||
555 			( *next != '\0' && *next != '.' ) )
556 			return -1;
557 		i = l << 8;
558 		if (*next == '.') {
559 			arg = next + 1;
560 			l = strtol( arg, &next, 10 );
561 			if ( l < 0 || l > 0xff || next == arg || *next != '\0' )
562 				return -1;
563 			i += l;
564 		}
565 		return ldap_pvt_tls_set_option( ld, option, &i );
566 		}
567 #ifdef HAVE_OPENSSL_CRL
568 	case LDAP_OPT_X_TLS_CRLCHECK:	/* OpenSSL only */
569 		i = -1;
570 		if ( strcasecmp( arg, "none" ) == 0 ) {
571 			i = LDAP_OPT_X_TLS_CRL_NONE ;
572 		} else if ( strcasecmp( arg, "peer" ) == 0 ) {
573 			i = LDAP_OPT_X_TLS_CRL_PEER ;
574 		} else if ( strcasecmp( arg, "all" ) == 0 ) {
575 			i = LDAP_OPT_X_TLS_CRL_ALL ;
576 		}
577 		if (i >= 0) {
578 			return ldap_pvt_tls_set_option( ld, option, &i );
579 		}
580 		return -1;
581 #endif
582 	}
583 	return -1;
584 }
585 
586 int
587 ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
588 {
589 	struct ldapoptions *lo;
590 
591 	if( ld != NULL ) {
592 		assert( LDAP_VALID( ld ) );
593 
594 		if( !LDAP_VALID( ld ) ) {
595 			return LDAP_OPT_ERROR;
596 		}
597 
598 		lo = &ld->ld_options;
599 
600 	} else {
601 		/* Get pointer to global option structure */
602 		lo = LDAP_INT_GLOBAL_OPT();
603 		if ( lo == NULL ) {
604 			return LDAP_NO_MEMORY;
605 		}
606 	}
607 
608 	switch( option ) {
609 	case LDAP_OPT_X_TLS:
610 		*(int *)arg = lo->ldo_tls_mode;
611 		break;
612 	case LDAP_OPT_X_TLS_CTX:
613 		*(void **)arg = lo->ldo_tls_ctx;
614 		if ( lo->ldo_tls_ctx ) {
615 			tls_ctx_ref( lo->ldo_tls_ctx );
616 		}
617 		break;
618 	case LDAP_OPT_X_TLS_CACERTFILE:
619 		*(char **)arg = lo->ldo_tls_cacertfile ?
620 			LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL;
621 		break;
622 	case LDAP_OPT_X_TLS_CACERTDIR:
623 		*(char **)arg = lo->ldo_tls_cacertdir ?
624 			LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL;
625 		break;
626 	case LDAP_OPT_X_TLS_CERTFILE:
627 		*(char **)arg = lo->ldo_tls_certfile ?
628 			LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL;
629 		break;
630 	case LDAP_OPT_X_TLS_KEYFILE:
631 		*(char **)arg = lo->ldo_tls_keyfile ?
632 			LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL;
633 		break;
634 	case LDAP_OPT_X_TLS_DHFILE:
635 		*(char **)arg = lo->ldo_tls_dhfile ?
636 			LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
637 		break;
638 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
639 		*(char **)arg = lo->ldo_tls_crlfile ?
640 			LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
641 		break;
642 	case LDAP_OPT_X_TLS_REQUIRE_CERT:
643 		*(int *)arg = lo->ldo_tls_require_cert;
644 		break;
645 #ifdef HAVE_OPENSSL_CRL
646 	case LDAP_OPT_X_TLS_CRLCHECK:	/* OpenSSL only */
647 		*(int *)arg = lo->ldo_tls_crlcheck;
648 		break;
649 #endif
650 	case LDAP_OPT_X_TLS_CIPHER_SUITE:
651 		*(char **)arg = lo->ldo_tls_ciphersuite ?
652 			LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL;
653 		break;
654 	case LDAP_OPT_X_TLS_PROTOCOL_MIN:
655 		*(int *)arg = lo->ldo_tls_protocol_min;
656 		break;
657 	case LDAP_OPT_X_TLS_RANDOM_FILE:
658 		*(char **)arg = lo->ldo_tls_randfile ?
659 			LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL;
660 		break;
661 	case LDAP_OPT_X_TLS_SSL_CTX: {
662 		void *retval = 0;
663 		if ( ld != NULL ) {
664 			LDAPConn *conn = ld->ld_defconn;
665 			if ( conn != NULL ) {
666 				Sockbuf *sb = conn->lconn_sb;
667 				retval = ldap_pvt_tls_sb_ctx( sb );
668 			}
669 		}
670 		*(void **)arg = retval;
671 		break;
672 	}
673 	case LDAP_OPT_X_TLS_CONNECT_CB:
674 		*(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb;
675 		break;
676 	case LDAP_OPT_X_TLS_CONNECT_ARG:
677 		*(void **)arg = lo->ldo_tls_connect_arg;
678 		break;
679 	default:
680 		return -1;
681 	}
682 	return 0;
683 }
684 
685 int
686 ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
687 {
688 	struct ldapoptions *lo;
689 
690 	if( ld != NULL ) {
691 		assert( LDAP_VALID( ld ) );
692 
693 		if( !LDAP_VALID( ld ) ) {
694 			return LDAP_OPT_ERROR;
695 		}
696 
697 		lo = &ld->ld_options;
698 
699 	} else {
700 		/* Get pointer to global option structure */
701 		lo = LDAP_INT_GLOBAL_OPT();
702 		if ( lo == NULL ) {
703 			return LDAP_NO_MEMORY;
704 		}
705 	}
706 
707 	switch( option ) {
708 	case LDAP_OPT_X_TLS:
709 		if ( !arg ) return -1;
710 
711 		switch( *(int *) arg ) {
712 		case LDAP_OPT_X_TLS_NEVER:
713 		case LDAP_OPT_X_TLS_DEMAND:
714 		case LDAP_OPT_X_TLS_ALLOW:
715 		case LDAP_OPT_X_TLS_TRY:
716 		case LDAP_OPT_X_TLS_HARD:
717 			if (lo != NULL) {
718 				lo->ldo_tls_mode = *(int *)arg;
719 			}
720 
721 			return 0;
722 		}
723 		return -1;
724 
725 	case LDAP_OPT_X_TLS_CTX:
726 		if ( lo->ldo_tls_ctx )
727 			ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
728 		lo->ldo_tls_ctx = arg;
729 		tls_ctx_ref( lo->ldo_tls_ctx );
730 		return 0;
731 	case LDAP_OPT_X_TLS_CONNECT_CB:
732 		lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg;
733 		return 0;
734 	case LDAP_OPT_X_TLS_CONNECT_ARG:
735 		lo->ldo_tls_connect_arg = arg;
736 		return 0;
737 	case LDAP_OPT_X_TLS_CACERTFILE:
738 		if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile );
739 		lo->ldo_tls_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
740 		return 0;
741 	case LDAP_OPT_X_TLS_CACERTDIR:
742 		if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir );
743 		lo->ldo_tls_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
744 		return 0;
745 	case LDAP_OPT_X_TLS_CERTFILE:
746 		if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile );
747 		lo->ldo_tls_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
748 		return 0;
749 	case LDAP_OPT_X_TLS_KEYFILE:
750 		if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile );
751 		lo->ldo_tls_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
752 		return 0;
753 	case LDAP_OPT_X_TLS_DHFILE:
754 		if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
755 		lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
756 		return 0;
757 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
758 		if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
759 		lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
760 		return 0;
761 	case LDAP_OPT_X_TLS_REQUIRE_CERT:
762 		if ( !arg ) return -1;
763 		switch( *(int *) arg ) {
764 		case LDAP_OPT_X_TLS_NEVER:
765 		case LDAP_OPT_X_TLS_DEMAND:
766 		case LDAP_OPT_X_TLS_ALLOW:
767 		case LDAP_OPT_X_TLS_TRY:
768 		case LDAP_OPT_X_TLS_HARD:
769 			lo->ldo_tls_require_cert = * (int *) arg;
770 			return 0;
771 		}
772 		return -1;
773 #ifdef HAVE_OPENSSL_CRL
774 	case LDAP_OPT_X_TLS_CRLCHECK:	/* OpenSSL only */
775 		if ( !arg ) return -1;
776 		switch( *(int *) arg ) {
777 		case LDAP_OPT_X_TLS_CRL_NONE:
778 		case LDAP_OPT_X_TLS_CRL_PEER:
779 		case LDAP_OPT_X_TLS_CRL_ALL:
780 			lo->ldo_tls_crlcheck = * (int *) arg;
781 			return 0;
782 		}
783 		return -1;
784 #endif
785 	case LDAP_OPT_X_TLS_CIPHER_SUITE:
786 		if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite );
787 		lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
788 		return 0;
789 
790 	case LDAP_OPT_X_TLS_PROTOCOL_MIN:
791 		if ( !arg ) return -1;
792 		lo->ldo_tls_protocol_min = *(int *)arg;
793 		return 0;
794 	case LDAP_OPT_X_TLS_RANDOM_FILE:
795 		if ( ld != NULL )
796 			return -1;
797 		if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile );
798 		lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
799 		break;
800 	case LDAP_OPT_X_TLS_NEWCTX:
801 		if ( !arg ) return -1;
802 		if ( lo->ldo_tls_ctx )
803 			ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
804 		lo->ldo_tls_ctx = NULL;
805 		return ldap_int_tls_init_ctx( lo, *(int *)arg );
806 	default:
807 		return -1;
808 	}
809 	return 0;
810 }
811 
812 int
813 ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
814 {
815 	Sockbuf *sb = conn->lconn_sb;
816 	char *host;
817 	void *ssl;
818 
819 	if( srv ) {
820 		host = srv->lud_host;
821 	} else {
822  		host = conn->lconn_server->lud_host;
823 	}
824 
825 	/* avoid NULL host */
826 	if( host == NULL ) {
827 		host = "localhost";
828 	}
829 
830 	(void) tls_init( tls_imp );
831 
832 	/*
833 	 * Fortunately, the lib uses blocking io...
834 	 */
835 	if ( ldap_int_tls_connect( ld, conn ) < 0 ) {
836 		ld->ld_errno = LDAP_CONNECT_ERROR;
837 		return (ld->ld_errno);
838 	}
839 
840 	ssl = ldap_pvt_tls_sb_ctx( sb );
841 	assert( ssl != NULL );
842 
843 	/*
844 	 * compare host with name(s) in certificate
845 	 */
846 	if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER) {
847 		ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
848 		if (ld->ld_errno != LDAP_SUCCESS) {
849 			return ld->ld_errno;
850 		}
851 	}
852 
853 	return LDAP_SUCCESS;
854 }
855 
856 void *
857 ldap_pvt_tls_sb_ctx( Sockbuf *sb )
858 {
859 	void			*p = NULL;
860 
861 	ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
862 	return p;
863 }
864 
865 int
866 ldap_pvt_tls_get_strength( void *s )
867 {
868 	tls_session *session = s;
869 
870 	return tls_imp->ti_session_strength( session );
871 }
872 
873 int
874 ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
875 {
876 	tls_session *session = s;
877 	struct berval der_dn;
878 	int rc;
879 
880 	rc = tls_imp->ti_session_my_dn( session, &der_dn );
881 	if ( rc == LDAP_SUCCESS )
882 		rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
883 	return rc;
884 }
885 #endif /* HAVE_TLS */
886 
887 int
888 ldap_start_tls( LDAP *ld,
889 	LDAPControl **serverctrls,
890 	LDAPControl **clientctrls,
891 	int *msgidp )
892 {
893 	return ldap_extended_operation( ld, LDAP_EXOP_START_TLS,
894 		NULL, serverctrls, clientctrls, msgidp );
895 }
896 
897 int
898 ldap_install_tls( LDAP *ld )
899 {
900 #ifndef HAVE_TLS
901 	return LDAP_NOT_SUPPORTED;
902 #else
903 	if ( ldap_tls_inplace( ld ) ) {
904 		return LDAP_LOCAL_ERROR;
905 	}
906 
907 	return ldap_int_tls_start( ld, ld->ld_defconn, NULL );
908 #endif
909 }
910 
911 int
912 ldap_start_tls_s ( LDAP *ld,
913 	LDAPControl **serverctrls,
914 	LDAPControl **clientctrls )
915 {
916 #ifndef HAVE_TLS
917 	return LDAP_NOT_SUPPORTED;
918 #else
919 	int rc;
920 	char *rspoid = NULL;
921 	struct berval *rspdata = NULL;
922 
923 	/* XXYYZ: this initiates operation only on default connection! */
924 
925 	if ( ldap_tls_inplace( ld ) ) {
926 		return LDAP_LOCAL_ERROR;
927 	}
928 
929 	rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS,
930 		NULL, serverctrls, clientctrls, &rspoid, &rspdata );
931 
932 	if ( rspoid != NULL ) {
933 		LDAP_FREE(rspoid);
934 	}
935 
936 	if ( rspdata != NULL ) {
937 		ber_bvfree( rspdata );
938 	}
939 
940 	if ( rc == LDAP_SUCCESS ) {
941 		rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL );
942 	}
943 
944 	return rc;
945 #endif
946 }
947 
948 /* These tags probably all belong in lber.h, but they're
949  * not normally encountered when processing LDAP, so maybe
950  * they belong somewhere else instead.
951  */
952 
953 #define LBER_TAG_OID		((ber_tag_t) 0x06UL)
954 
955 /* Tags for string types used in a DirectoryString.
956  *
957  * Note that IA5string is not one of the defined choices for
958  * DirectoryString in X.520, but it gets used for email AVAs.
959  */
960 #define	LBER_TAG_UTF8		((ber_tag_t) 0x0cUL)
961 #define	LBER_TAG_PRINTABLE	((ber_tag_t) 0x13UL)
962 #define	LBER_TAG_TELETEX	((ber_tag_t) 0x14UL)
963 #define	LBER_TAG_IA5		((ber_tag_t) 0x16UL)
964 #define	LBER_TAG_UNIVERSAL	((ber_tag_t) 0x1cUL)
965 #define	LBER_TAG_BMP		((ber_tag_t) 0x1eUL)
966 
967 static oid_name *
968 find_oid( struct berval *oid )
969 {
970 	int i;
971 
972 	for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) {
973 		if ( oids[i].oid.bv_len != oid->bv_len ) continue;
974 		if ( !strcmp( oids[i].oid.bv_val, oid->bv_val ))
975 			return &oids[i];
976 	}
977 	return NULL;
978 }
979 
980 /* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
981  * x509_name must be raw DER. If func is non-NULL, the
982  * constructed DN will use numeric OIDs to identify attributeTypes,
983  * and the func() will be invoked to rewrite the DN with the given
984  * flags.
985  *
986  * Otherwise the DN will use shortNames from a hardcoded table.
987  */
988 int
989 ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
990 	unsigned flags )
991 {
992 	LDAPDN	newDN;
993 	LDAPRDN	newRDN;
994 	LDAPAVA *newAVA, *baseAVA;
995 	BerElementBuffer berbuf;
996 	BerElement *ber = (BerElement *)&berbuf;
997 	char oids[8192], *oidptr = oids, *oidbuf = NULL;
998 	void *ptrs[2048];
999 	char *dn_end, *rdn_end;
1000 	int i, navas, nrdns, rc = LDAP_SUCCESS;
1001 	size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
1002 	int csize;
1003 	ber_tag_t tag;
1004 	ber_len_t len;
1005 	oid_name *oidname;
1006 
1007 	struct berval	Oid, Val, oid2, *in = x509_name;
1008 
1009 	assert( bv != NULL );
1010 
1011 	bv->bv_len = 0;
1012 	bv->bv_val = NULL;
1013 
1014 	navas = 0;
1015 	nrdns = 0;
1016 
1017 	/* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs.
1018 	 * An AVA is a SEQUENCE of attr and value.
1019 	 * Count the number of AVAs and RDNs
1020 	 */
1021 	ber_init2( ber, in, LBER_USE_DER );
1022 	tag = ber_peek_tag( ber, &len );
1023 	if ( tag != LBER_SEQUENCE )
1024 		return LDAP_DECODING_ERROR;
1025 
1026 	for ( tag = ber_first_element( ber, &len, &dn_end );
1027 		tag == LBER_SET;
1028 		tag = ber_next_element( ber, &len, dn_end )) {
1029 		nrdns++;
1030 		for ( tag = ber_first_element( ber, &len, &rdn_end );
1031 			tag == LBER_SEQUENCE;
1032 			tag = ber_next_element( ber, &len, rdn_end )) {
1033 			tag = ber_skip_tag( ber, &len );
1034 			ber_skip_data( ber, len );
1035 			navas++;
1036 		}
1037 	}
1038 
1039 	/* Allocate the DN/RDN/AVA stuff as a single block */
1040 	dnsize = sizeof(LDAPRDN) * (nrdns+1);
1041 	dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
1042 	dnsize += sizeof(LDAPAVA) * navas;
1043 	if (dnsize > sizeof(ptrs)) {
1044 		newDN = (LDAPDN)LDAP_MALLOC( dnsize );
1045 		if ( newDN == NULL )
1046 			return LDAP_NO_MEMORY;
1047 	} else {
1048 		newDN = (LDAPDN)(char *)ptrs;
1049 	}
1050 
1051 	newDN[nrdns] = NULL;
1052 	newRDN = (LDAPRDN)(newDN + nrdns+1);
1053 	newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
1054 	baseAVA = newAVA;
1055 
1056 	/* Rewind and start extracting */
1057 	ber_rewind( ber );
1058 
1059 	tag = ber_first_element( ber, &len, &dn_end );
1060 	for ( i = nrdns - 1; i >= 0; i-- ) {
1061 		newDN[i] = newRDN;
1062 
1063 		for ( tag = ber_first_element( ber, &len, &rdn_end );
1064 			tag == LBER_SEQUENCE;
1065 			tag = ber_next_element( ber, &len, rdn_end )) {
1066 
1067 			*newRDN++ = newAVA;
1068 			tag = ber_skip_tag( ber, &len );
1069 			tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM );
1070 			if ( tag != LBER_TAG_OID ) {
1071 				rc = LDAP_DECODING_ERROR;
1072 				goto nomem;
1073 			}
1074 
1075 			oid2.bv_val = oidptr;
1076 			oid2.bv_len = oidrem;
1077 			if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) {
1078 				rc = LDAP_DECODING_ERROR;
1079 				goto nomem;
1080 			}
1081 			oidname = find_oid( &oid2 );
1082 			if ( !oidname ) {
1083 				newAVA->la_attr = oid2;
1084 				oidptr += oid2.bv_len + 1;
1085 				oidrem -= oid2.bv_len + 1;
1086 
1087 				/* Running out of OID buffer space? */
1088 				if (oidrem < 128) {
1089 					if ( oidsize == 0 ) {
1090 						oidsize = sizeof(oids) * 2;
1091 						oidrem = oidsize;
1092 						oidbuf = LDAP_MALLOC( oidsize );
1093 						if ( oidbuf == NULL ) goto nomem;
1094 						oidptr = oidbuf;
1095 					} else {
1096 						char *old = oidbuf;
1097 						oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
1098 						if ( oidbuf == NULL ) goto nomem;
1099 						/* Buffer moved! Fix AVA pointers */
1100 						if ( old != oidbuf ) {
1101 							LDAPAVA *a;
1102 							long dif = oidbuf - old;
1103 
1104 							for (a=baseAVA; a<=newAVA; a++){
1105 								if (a->la_attr.bv_val >= old &&
1106 									a->la_attr.bv_val <= (old + oidsize))
1107 									a->la_attr.bv_val += dif;
1108 							}
1109 						}
1110 						oidptr = oidbuf + oidsize - oidrem;
1111 						oidrem += oidsize;
1112 						oidsize *= 2;
1113 					}
1114 				}
1115 			} else {
1116 				if ( func ) {
1117 					newAVA->la_attr = oidname->oid;
1118 				} else {
1119 					newAVA->la_attr = oidname->name;
1120 				}
1121 			}
1122 			tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM );
1123 			switch(tag) {
1124 			case LBER_TAG_UNIVERSAL:
1125 				/* This uses 32-bit ISO 10646-1 */
1126 				csize = 4; goto to_utf8;
1127 			case LBER_TAG_BMP:
1128 				/* This uses 16-bit ISO 10646-1 */
1129 				csize = 2; goto to_utf8;
1130 			case LBER_TAG_TELETEX:
1131 				/* This uses 8-bit, assume ISO 8859-1 */
1132 				csize = 1;
1133 to_utf8:		rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
1134 				newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
1135 				if (rc != LDAP_SUCCESS) goto nomem;
1136 				newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
1137 				break;
1138 			case LBER_TAG_UTF8:
1139 				newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
1140 				/* This is already in UTF-8 encoding */
1141 			case LBER_TAG_IA5:
1142 			case LBER_TAG_PRINTABLE:
1143 				/* These are always 7-bit strings */
1144 				newAVA->la_value = Val;
1145 			default:
1146 				;
1147 			}
1148 			newAVA->la_private = NULL;
1149 			newAVA->la_flags = LDAP_AVA_STRING;
1150 			newAVA++;
1151 		}
1152 		*newRDN++ = NULL;
1153 		tag = ber_next_element( ber, &len, dn_end );
1154 	}
1155 
1156 	if ( func ) {
1157 		rc = func( newDN, flags, NULL );
1158 		if ( rc != LDAP_SUCCESS )
1159 			goto nomem;
1160 	}
1161 
1162 	rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
1163 
1164 nomem:
1165 	for (;baseAVA < newAVA; baseAVA++) {
1166 		if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
1167 			LDAP_FREE( baseAVA->la_attr.bv_val );
1168 		if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
1169 			LDAP_FREE( baseAVA->la_value.bv_val );
1170 	}
1171 
1172 	if ( oidsize != 0 )
1173 		LDAP_FREE( oidbuf );
1174 	if ( newDN != (LDAPDN)(char *) ptrs )
1175 		LDAP_FREE( newDN );
1176 	return rc;
1177 }
1178 
1179