1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2011 The OpenLDAP Foundation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
10 *
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
14 */
15
16#include "portable.h"
17
18#include <stdio.h>
19#include <ac/stdlib.h>
20
21#ifdef HAVE_GETEUID
22#include <ac/unistd.h>
23#endif
24
25#include <ac/socket.h>
26#include <ac/string.h>
27#include <ac/ctype.h>
28#include <ac/time.h>
29
30#ifdef HAVE_LIMITS_H
31#include <limits.h>
32#endif
33
34#include "ldap-int.h"
35#include "ldap_defaults.h"
36#include "lutil.h"
37
38struct ldapoptions ldap_int_global_options =
39	{ LDAP_UNINITIALIZED, LDAP_DEBUG_NONE LDAP_LDO_MUTEX_NULLARG };
40
41#ifdef __APPLE__
42#include <pthread.h>
43static pthread_mutex_t _init_lock_data_ = PTHREAD_MUTEX_INITIALIZER;
44static pthread_mutex_t _init_lock_main_ = PTHREAD_MUTEX_INITIALIZER;
45static int _init_lock_count_ = 0;
46static pthread_t _init_thread_ = (pthread_t)-1;
47#endif
48
49#define ATTR_NONE	0
50#define ATTR_BOOL	1
51#define ATTR_INT	2
52#define ATTR_KV		3
53#define ATTR_STRING	4
54#define ATTR_OPTION	5
55
56#define ATTR_SASL	6
57#define ATTR_TLS	7
58
59#define ATTR_OPT_TV	8
60#define ATTR_OPT_INT	9
61
62#define ATTR_GSSAPI	10
63
64struct ol_keyvalue {
65	const char *		key;
66	int			value;
67};
68
69static const struct ol_keyvalue deref_kv[] = {
70	{"never", LDAP_DEREF_NEVER},
71	{"searching", LDAP_DEREF_SEARCHING},
72	{"finding", LDAP_DEREF_FINDING},
73	{"always", LDAP_DEREF_ALWAYS},
74	{NULL, 0}
75};
76
77static const struct ol_attribute {
78	int			useronly;
79	int			type;
80	const char *	name;
81	const void *	data;
82	size_t		offset;
83} attrs[] = {
84	{0, ATTR_OPT_TV,	"TIMEOUT",		NULL,	LDAP_OPT_TIMEOUT},
85	{0, ATTR_OPT_TV,	"NETWORK_TIMEOUT",	NULL,	LDAP_OPT_NETWORK_TIMEOUT},
86	{0, ATTR_OPT_INT,	"VERSION",		NULL,	LDAP_OPT_PROTOCOL_VERSION},
87	{0, ATTR_KV,		"DEREF",	deref_kv, /* or &deref_kv[0] */
88		offsetof(struct ldapoptions, ldo_deref)},
89	{0, ATTR_INT,		"SIZELIMIT",	NULL,
90		offsetof(struct ldapoptions, ldo_sizelimit)},
91	{0, ATTR_INT,		"TIMELIMIT",	NULL,
92		offsetof(struct ldapoptions, ldo_timelimit)},
93	{1, ATTR_STRING,	"BINDDN",		NULL,
94		offsetof(struct ldapoptions, ldo_defbinddn)},
95	{0, ATTR_STRING,	"BASE",			NULL,
96		offsetof(struct ldapoptions, ldo_defbase)},
97	{0, ATTR_INT,		"PORT",			NULL,		/* deprecated */
98		offsetof(struct ldapoptions, ldo_defport)},
99	{0, ATTR_OPTION,	"HOST",			NULL,	LDAP_OPT_HOST_NAME}, /* deprecated */
100	{0, ATTR_OPTION,	"URI",			NULL,	LDAP_OPT_URI}, /* replaces HOST/PORT */
101	{0, ATTR_BOOL,		"REFERRALS",	NULL,	LDAP_BOOL_REFERRALS},
102#if 0
103	/* This should only be allowed via ldap_set_option(3) */
104	{0, ATTR_BOOL,		"RESTART",		NULL,	LDAP_BOOL_RESTART},
105#endif
106
107#ifdef HAVE_CYRUS_SASL
108	{0, ATTR_STRING,	"SASL_MECH",		NULL,
109		offsetof(struct ldapoptions, ldo_def_sasl_mech)},
110	{0, ATTR_STRING,	"SASL_REALM",		NULL,
111		offsetof(struct ldapoptions, ldo_def_sasl_realm)},
112	{1, ATTR_STRING,	"SASL_AUTHCID",		NULL,
113		offsetof(struct ldapoptions, ldo_def_sasl_authcid)},
114	{1, ATTR_STRING,	"SASL_AUTHZID",		NULL,
115		offsetof(struct ldapoptions, ldo_def_sasl_authzid)},
116	{0, ATTR_SASL,		"SASL_SECPROPS",	NULL,	LDAP_OPT_X_SASL_SECPROPS},
117	{0, ATTR_BOOL,		"SASL_NOCANON",	NULL,	LDAP_BOOL_SASL_NOCANON},
118#endif
119
120#ifdef HAVE_GSSAPI
121	{0, ATTR_GSSAPI,"GSSAPI_SIGN",			NULL,	LDAP_OPT_SIGN},
122	{0, ATTR_GSSAPI,"GSSAPI_ENCRYPT",		NULL,	LDAP_OPT_ENCRYPT},
123	{0, ATTR_GSSAPI,"GSSAPI_ALLOW_REMOTE_PRINCIPAL",NULL,	LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL},
124#endif
125
126#ifdef HAVE_TLS
127#ifdef HAVE_SECURE_TRANSPORT
128	{1, ATTR_TLS,	"TLS_IDENTITY",		NULL,	LDAP_OPT_X_TLS_IDENTITY},
129  	{0, ATTR_TLS,	"TLS_TRUSTED_CERTS",NULL,	LDAP_OPT_X_TLS_TRUSTED_CERTS},
130#else
131	{1, ATTR_TLS,	"TLS_CERT",			NULL,	LDAP_OPT_X_TLS_CERTFILE},
132	{1, ATTR_TLS,	"TLS_KEY",			NULL,	LDAP_OPT_X_TLS_KEYFILE},
133  	{0, ATTR_TLS,	"TLS_CACERT",		NULL,	LDAP_OPT_X_TLS_CACERTFILE},
134  	{0, ATTR_TLS,	"TLS_CACERTDIR",	NULL,	LDAP_OPT_X_TLS_CACERTDIR},
135#endif
136  	{0, ATTR_TLS,	"TLS_REQCERT",		NULL,	LDAP_OPT_X_TLS_REQUIRE_CERT},
137#ifndef HAVE_SECURE_TRANSPORT
138	{0, ATTR_TLS,	"TLS_RANDFILE",		NULL,	LDAP_OPT_X_TLS_RANDOM_FILE},
139#endif
140	{0, ATTR_TLS,	"TLS_CIPHER_SUITE",	NULL,	LDAP_OPT_X_TLS_CIPHER_SUITE},
141	{0, ATTR_TLS,	"TLS_PROTOCOL_MIN",	NULL,	LDAP_OPT_X_TLS_PROTOCOL_MIN},
142
143#if defined(HAVE_OPENSSL_CRL) || defined(HAVE_SECURE_TRANSPORT)
144	{0, ATTR_TLS,	"TLS_CRLCHECK",		NULL,	LDAP_OPT_X_TLS_CRLCHECK},
145#endif
146#ifdef HAVE_GNUTLS
147	{0, ATTR_TLS,	"TLS_CRLFILE",			NULL,	LDAP_OPT_X_TLS_CRLFILE},
148#endif
149
150#endif
151
152	{0, ATTR_NONE,		NULL,		NULL,	0}
153};
154
155#define MAX_LDAP_ATTR_LEN  sizeof("GSSAPI_ALLOW_REMOTE_PRINCIPAL")
156#define MAX_LDAP_ENV_PREFIX_LEN 8
157
158#ifdef __APPLE__
159void _lock_init(void)
160{
161	pthread_t t;
162
163	t = pthread_self();
164
165	pthread_mutex_lock(&_init_lock_data_);
166	if ((_init_lock_count_ > 0) && (_init_thread_ == t))
167	{
168		/* Recursive lock: just increment the locked counter */
169		_init_lock_count_++;
170		pthread_mutex_unlock(&_init_lock_data_);
171		return;
172	}
173	pthread_mutex_unlock(&_init_lock_data_);
174
175	pthread_mutex_lock(&_init_lock_main_);
176
177	pthread_mutex_lock(&_init_lock_data_);
178	_init_lock_count_ = 1;
179	_init_thread_ = t;
180	pthread_mutex_unlock(&_init_lock_data_);
181}
182
183void _unlock_init(void)
184{
185	int unlock_me;
186
187	unlock_me = 0;
188
189	pthread_mutex_lock(&_init_lock_data_);
190	if (_init_lock_count_ > 0) _init_lock_count_--;
191	if (_init_lock_count_ == 0)
192	{
193		_init_thread_ = (pthread_t)-1;
194		unlock_me = 1;
195	}
196	pthread_mutex_unlock(&_init_lock_data_);
197
198	if (unlock_me == 1) pthread_mutex_unlock(&_init_lock_main_);
199}
200
201dispatch_once_t ldap_global_opts_initialized = 0;
202void ldap_int_init_global_opts(void)
203{
204	struct ldapoptions	*gopts;
205
206	/* Get pointer to global option structure */
207	if ( (gopts = LDAP_INT_GLOBAL_OPT()) != NULL) {
208		if ( gopts->ldo_valid != LDAP_INITIALIZED ) {
209			ldap_int_initialize(gopts, NULL);
210		}
211	}
212}
213#endif
214
215static void openldap_ldap_init_w_conf(
216	const char *file, int userconf )
217{
218	char linebuf[ AC_LINE_MAX ];
219	FILE *fp;
220	int i;
221	char *cmd, *opt;
222	char *start, *end;
223	struct ldapoptions *gopts;
224
225	if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
226		return;			/* Could not allocate mem for global options */
227	}
228
229	if (file == NULL) {
230		/* no file name */
231		return;
232	}
233
234	Debug(LDAP_DEBUG_TRACE, "ldap_init: trying %s\n", file, 0, 0);
235
236	fp = fopen(file, "r");
237	if(fp == NULL) {
238		/* could not open file */
239		return;
240	}
241
242	Debug(LDAP_DEBUG_TRACE, "ldap_init: using %s\n", file, 0, 0);
243
244	while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) {
245		/* skip lines starting with '#' */
246		if(*start == '#') continue;
247
248		/* trim leading white space */
249		while((*start != '\0') && isspace((unsigned char) *start))
250			start++;
251
252		/* anything left? */
253		if(*start == '\0') continue;
254
255		/* trim trailing white space */
256		end = &start[strlen(start)-1];
257		while(isspace((unsigned char)*end)) end--;
258		end[1] = '\0';
259
260		/* anything left? */
261		if(*start == '\0') continue;
262
263
264		/* parse the command */
265		cmd=start;
266		while((*start != '\0') && !isspace((unsigned char)*start)) {
267			start++;
268		}
269		if(*start == '\0') {
270			/* command has no argument */
271			continue;
272		}
273
274		*start++ = '\0';
275
276		/* we must have some whitespace to skip */
277		while(isspace((unsigned char)*start)) start++;
278		opt = start;
279
280		for(i=0; attrs[i].type != ATTR_NONE; i++) {
281			void *p;
282
283			if( !userconf && attrs[i].useronly ) {
284				continue;
285			}
286
287			if(strcasecmp(cmd, attrs[i].name) != 0) {
288				continue;
289			}
290
291			switch(attrs[i].type) {
292			case ATTR_BOOL:
293				if((strcasecmp(opt, "on") == 0)
294					|| (strcasecmp(opt, "yes") == 0)
295					|| (strcasecmp(opt, "true") == 0))
296				{
297					LDAP_BOOL_SET(gopts, attrs[i].offset);
298
299				} else {
300					LDAP_BOOL_CLR(gopts, attrs[i].offset);
301				}
302
303				break;
304
305			case ATTR_INT: {
306				char *next;
307				long l;
308				p = &((char *) gopts)[attrs[i].offset];
309				l = strtol( opt, &next, 10 );
310				if ( next != opt && next[ 0 ] == '\0' ) {
311					* (int*) p = l;
312				}
313				} break;
314
315			case ATTR_KV: {
316					const struct ol_keyvalue *kv;
317
318					for(kv = attrs[i].data;
319						kv->key != NULL;
320						kv++) {
321
322						if(strcasecmp(opt, kv->key) == 0) {
323							p = &((char *) gopts)[attrs[i].offset];
324							* (int*) p = kv->value;
325							break;
326						}
327					}
328				} break;
329
330			case ATTR_STRING:
331				p = &((char *) gopts)[attrs[i].offset];
332				if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
333				* (char**) p = LDAP_STRDUP(opt);
334				break;
335			case ATTR_OPTION:
336				ldap_set_option( NULL, attrs[i].offset, opt );
337				break;
338			case ATTR_SASL:
339#ifdef HAVE_CYRUS_SASL
340			   	ldap_int_sasl_config( gopts, attrs[i].offset, opt );
341#endif
342				break;
343			case ATTR_GSSAPI:
344#ifdef HAVE_GSSAPI
345				ldap_int_gssapi_config( gopts, attrs[i].offset, opt );
346#endif
347				break;
348			case ATTR_TLS:
349#ifdef HAVE_TLS
350			   	ldap_int_tls_config( NULL, attrs[i].offset, opt );
351#endif
352				break;
353			case ATTR_OPT_TV: {
354				struct timeval tv;
355				char *next;
356				tv.tv_usec = 0;
357				tv.tv_sec = strtol( opt, &next, 10 );
358				if ( next != opt && next[ 0 ] == '\0' && tv.tv_sec > 0 ) {
359					(void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv );
360				}
361				} break;
362			case ATTR_OPT_INT: {
363				long l;
364				char *next;
365				l = strtol( opt, &next, 10 );
366				if ( next != opt && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) {
367					int v = (int)l;
368					(void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v );
369				}
370				} break;
371			}
372
373			break;
374		}
375	}
376
377	fclose(fp);
378}
379
380static void openldap_ldap_init_w_sysconf(const char *file)
381{
382	openldap_ldap_init_w_conf( file, 0 );
383}
384
385static void openldap_ldap_init_w_userconf(const char *file)
386{
387	char *home;
388	char *path = NULL;
389
390	if (file == NULL) {
391		/* no file name */
392		return;
393	}
394
395	home = getenv("HOME");
396
397	if (home != NULL) {
398		Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is %s\n",
399		      home, 0, 0);
400		path = LDAP_MALLOC(strlen(home) + strlen(file) + sizeof( LDAP_DIRSEP "."));
401	} else {
402		Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is NULL\n",
403		      0, 0, 0);
404	}
405
406	if(home != NULL && path != NULL) {
407		/* we assume UNIX path syntax is used... */
408
409		/* try ~/file */
410		sprintf(path, "%s" LDAP_DIRSEP "%s", home, file);
411		openldap_ldap_init_w_conf(path, 1);
412
413		/* try ~/.file */
414		sprintf(path, "%s" LDAP_DIRSEP ".%s", home, file);
415		openldap_ldap_init_w_conf(path, 1);
416	}
417
418	if(path != NULL) {
419		LDAP_FREE(path);
420	}
421
422	/* try file */
423	openldap_ldap_init_w_conf(file, 1);
424}
425
426static void openldap_ldap_init_w_env(
427		struct ldapoptions *gopts,
428		const char *prefix)
429{
430	char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN];
431	int len;
432	int i;
433	void *p;
434	char *value;
435
436	if (prefix == NULL) {
437		prefix = LDAP_ENV_PREFIX;
438	}
439
440	strncpy(buf, prefix, MAX_LDAP_ENV_PREFIX_LEN);
441	buf[MAX_LDAP_ENV_PREFIX_LEN] = '\0';
442	len = strlen(buf);
443
444	for(i=0; attrs[i].type != ATTR_NONE; i++) {
445		strcpy(&buf[len], attrs[i].name);
446		value = getenv(buf);
447
448		if(value == NULL) {
449			continue;
450		}
451
452		switch(attrs[i].type) {
453		case ATTR_BOOL:
454			if((strcasecmp(value, "on") == 0)
455				|| (strcasecmp(value, "yes") == 0)
456				|| (strcasecmp(value, "true") == 0))
457			{
458				LDAP_BOOL_SET(gopts, attrs[i].offset);
459
460			} else {
461				LDAP_BOOL_CLR(gopts, attrs[i].offset);
462			}
463			break;
464
465		case ATTR_INT:
466			p = &((char *) gopts)[attrs[i].offset];
467			* (int*) p = atoi(value);
468			break;
469
470		case ATTR_KV: {
471				const struct ol_keyvalue *kv;
472
473				for(kv = attrs[i].data;
474					kv->key != NULL;
475					kv++) {
476
477					if(strcasecmp(value, kv->key) == 0) {
478						p = &((char *) gopts)[attrs[i].offset];
479						* (int*) p = kv->value;
480						break;
481					}
482				}
483			} break;
484
485		case ATTR_STRING:
486			p = &((char *) gopts)[attrs[i].offset];
487			if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
488			if (*value == '\0') {
489				* (char**) p = NULL;
490			} else {
491				* (char**) p = LDAP_STRDUP(value);
492			}
493			break;
494		case ATTR_OPTION:
495			ldap_set_option( NULL, attrs[i].offset, value );
496			break;
497		case ATTR_SASL:
498#ifdef HAVE_CYRUS_SASL
499		   	ldap_int_sasl_config( gopts, attrs[i].offset, value );
500#endif
501		   	break;
502		case ATTR_GSSAPI:
503#ifdef HAVE_GSSAPI
504			ldap_int_gssapi_config( gopts, attrs[i].offset, value );
505#endif
506			break;
507		case ATTR_TLS:
508#ifdef HAVE_TLS
509		   	ldap_int_tls_config( NULL, attrs[i].offset, value );
510#endif
511		   	break;
512		case ATTR_OPT_TV: {
513			struct timeval tv;
514			char *next;
515			tv.tv_usec = 0;
516			tv.tv_sec = strtol( value, &next, 10 );
517			if ( next != value && next[ 0 ] == '\0' && tv.tv_sec > 0 ) {
518				(void)ldap_set_option( NULL, attrs[i].offset, (const void *)&tv );
519			}
520			} break;
521		case ATTR_OPT_INT: {
522			long l;
523			char *next;
524			l = strtol( value, &next, 10 );
525			if ( next != value && next[ 0 ] == '\0' && l > 0 && (long)((int)l) == l ) {
526				int v = (int)l;
527				(void)ldap_set_option( NULL, attrs[i].offset, (const void *)&v );
528			}
529			} break;
530		}
531	}
532}
533
534#if defined(__GNUC__)
535/* Declare this function as a destructor so that it will automatically be
536 * invoked either at program exit (if libldap is a static library) or
537 * at unload time (if libldap is a dynamic library).
538 *
539 * Sorry, don't know how to handle this for non-GCC environments.
540 */
541static void ldap_int_destroy_global_options(void)
542	__attribute__ ((destructor));
543#endif
544
545static void
546ldap_int_destroy_global_options(void)
547{
548	struct ldapoptions *gopts = LDAP_INT_GLOBAL_OPT();
549
550	if ( gopts == NULL )
551		return;
552
553	gopts->ldo_valid = LDAP_UNINITIALIZED;
554
555	if ( gopts->ldo_defludp ) {
556		ldap_free_urllist( gopts->ldo_defludp );
557		gopts->ldo_defludp = NULL;
558	}
559#if defined(HAVE_WINSOCK) || defined(HAVE_WINSOCK2)
560	WSACleanup( );
561#endif
562
563#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
564	if ( ldap_int_hostname ) {
565		LDAP_FREE( ldap_int_hostname );
566		ldap_int_hostname = NULL;
567	}
568#endif
569#ifdef HAVE_CYRUS_SASL
570	if ( gopts->ldo_def_sasl_authcid ) {
571		LDAP_FREE( gopts->ldo_def_sasl_authcid );
572		gopts->ldo_def_sasl_authcid = NULL;
573	}
574#endif
575#ifdef HAVE_TLS
576	ldap_int_tls_destroy( gopts );
577#endif
578}
579
580/*
581 * Initialize the global options structure with default values.
582 */
583void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl )
584{
585#ifdef LDAP_R_COMPILE
586	LDAP_PVT_MUTEX_FIRSTCREATE(gopts->ldo_mutex);
587#endif
588	LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
589	if (gopts->ldo_valid == LDAP_INITIALIZED) {
590		/* someone else got here first */
591		LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
592		return;
593	}
594	if (dbglvl)
595	    gopts->ldo_debug = *dbglvl;
596	else
597		gopts->ldo_debug = 0;
598
599	gopts->ldo_version   = LDAP_VERSION2;
600	gopts->ldo_deref     = LDAP_DEREF_NEVER;
601	gopts->ldo_timelimit = LDAP_NO_LIMIT;
602	gopts->ldo_sizelimit = LDAP_NO_LIMIT;
603
604	gopts->ldo_tm_api.tv_sec = -1;
605	gopts->ldo_tm_net.tv_sec = -1;
606
607	/* ldo_defludp will be freed by the termination handler
608	 */
609	ldap_url_parselist(&gopts->ldo_defludp, "ldap://localhost/");
610	gopts->ldo_defport = LDAP_PORT;
611#if !defined(__GNUC__) && !defined(PIC)
612	/* Do this only for a static library, and only if we can't
613	 * arrange for it to be executed as a library destructor
614	 */
615	atexit(ldap_int_destroy_global_options);
616#endif
617
618	gopts->ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
619	gopts->ldo_rebind_proc = NULL;
620	gopts->ldo_rebind_params = NULL;
621
622	LDAP_BOOL_ZERO(gopts);
623
624	LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS);
625
626#ifdef LDAP_CONNECTIONLESS
627	gopts->ldo_peer = NULL;
628	gopts->ldo_cldapdn = NULL;
629	gopts->ldo_is_udp = 0;
630#endif
631
632#ifdef HAVE_CYRUS_SASL
633	gopts->ldo_def_sasl_mech = NULL;
634	gopts->ldo_def_sasl_realm = NULL;
635	gopts->ldo_def_sasl_authcid = NULL;
636	gopts->ldo_def_sasl_authzid = NULL;
637
638	memset( &gopts->ldo_sasl_secprops,
639		'\0', sizeof(gopts->ldo_sasl_secprops) );
640
641	gopts->ldo_sasl_secprops.max_ssf = INT_MAX;
642	gopts->ldo_sasl_secprops.maxbufsize = SASL_MAX_BUFF_SIZE;
643	gopts->ldo_sasl_secprops.security_flags =
644		SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS;
645#endif
646
647#ifdef HAVE_TLS
648	gopts->ldo_tls_connect_cb = NULL;
649	gopts->ldo_tls_connect_arg = NULL;
650	gopts->ldo_tls_require_cert = LDAP_OPT_X_TLS_DEMAND;
651#ifndef HAVE_SECURE_TRANSPORT
652	gopts->ldo_tls_cert_ref = NULL;
653#endif
654#endif
655	gopts->ldo_keepalive_probes = 0;
656	gopts->ldo_keepalive_interval = 0;
657	gopts->ldo_keepalive_idle = 0;
658
659	gopts->ldo_valid = LDAP_INITIALIZED;
660	LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
661   	return;
662}
663
664#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
665char * ldap_int_hostname = NULL;
666#endif
667
668void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl )
669{
670#ifdef __APPLE__
671	_lock_init();
672#endif
673	if ( gopts->ldo_valid == LDAP_INITIALIZED ) {
674#ifdef __APPLE__
675		_unlock_init();
676#endif
677		return;
678	}
679
680	ldap_int_error_init();
681
682	ldap_int_utils_init();
683
684#ifdef HAVE_WINSOCK2
685{	WORD wVersionRequested;
686	WSADATA wsaData;
687
688	wVersionRequested = MAKEWORD( 2, 0 );
689	if ( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
690		/* Tell the user that we couldn't find a usable */
691		/* WinSock DLL.                                  */
692#ifdef __APPLE__
693		_unlock_init();
694#endif
695		return;
696	}
697
698	/* Confirm that the WinSock DLL supports 2.0.*/
699	/* Note that if the DLL supports versions greater    */
700	/* than 2.0 in addition to 2.0, it will still return */
701	/* 2.0 in wVersion since that is the version we      */
702	/* requested.                                        */
703
704	if ( LOBYTE( wsaData.wVersion ) != 2 ||
705		HIBYTE( wsaData.wVersion ) != 0 )
706	{
707	    /* Tell the user that we couldn't find a usable */
708	    /* WinSock DLL.                                  */
709	    WSACleanup( );
710#ifdef __APPLE__
711		_unlock_init();
712#endif
713		return;
714	}
715}	/* The WinSock DLL is acceptable. Proceed. */
716#elif defined(HAVE_WINSOCK)
717{	WSADATA wsaData;
718	if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
719#ifdef __APPLE__
720		_unlock_init();
721#endif
722	    return;
723	}
724}
725#endif
726
727#if defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
728	{
729		char	*name = ldap_int_hostname;
730
731		ldap_int_hostname = ldap_pvt_get_fqdn( name );
732
733		if ( name != NULL && name != ldap_int_hostname ) {
734			LDAP_FREE( name );
735		}
736	}
737#endif
738
739#ifndef HAVE_POLL
740	if ( ldap_int_tblsize == 0 ) ldap_int_ip_init();
741#endif
742
743	ldap_int_initialize_global_options(gopts, NULL);
744
745	if( getenv("LDAPNOINIT") != NULL ) {
746#ifdef __APPLE__
747		_unlock_init();
748#endif
749		return;
750	}
751
752#ifdef HAVE_CYRUS_SASL
753	{
754		/* set authentication identity to current user name */
755		char *user = getenv("USER");
756
757		if( user == NULL ) user = getenv("USERNAME");
758		if( user == NULL ) user = getenv("LOGNAME");
759
760		if( user != NULL ) {
761			gopts->ldo_def_sasl_authcid = LDAP_STRDUP( user );
762		}
763    }
764#endif
765
766	openldap_ldap_init_w_sysconf(LDAP_CONF_FILE);
767
768#ifdef HAVE_GETEUID
769	if ( geteuid() != getuid() )
770		return;
771#endif
772
773	openldap_ldap_init_w_userconf(LDAP_USERRC_FILE);
774
775	{
776		char *altfile = getenv(LDAP_ENV_PREFIX "CONF");
777
778		if( altfile != NULL ) {
779			Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n",
780			      LDAP_ENV_PREFIX "CONF", altfile, 0);
781			openldap_ldap_init_w_sysconf( altfile );
782		}
783		else
784			Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n",
785			      LDAP_ENV_PREFIX "CONF", 0, 0);
786	}
787
788	{
789		char *altfile = getenv(LDAP_ENV_PREFIX "RC");
790
791		if( altfile != NULL ) {
792			Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n",
793			      LDAP_ENV_PREFIX "RC", altfile, 0);
794			openldap_ldap_init_w_userconf( altfile );
795		}
796		else
797			Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n",
798			      LDAP_ENV_PREFIX "RC", 0, 0);
799	}
800
801	openldap_ldap_init_w_env(gopts, NULL);
802
803	ldap_int_sasl_init();
804#ifdef __APPLE__
805	_unlock_init();
806#endif
807}
808