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