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