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