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