xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/options.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: options.c,v 1.3 2021/08/14 16:14:56 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: options.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include <ac/stdlib.h>
26 
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30 
31 #include "ldap-int.h"
32 
33 #define LDAP_OPT_REBIND_PROC 0x4e814d
34 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
35 
36 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
37 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
38 
39 #define LDAP_OPT_URLLIST_PROC 0x4e816d
40 #define LDAP_OPT_URLLIST_PARAMS 0x4e816e
41 
42 static const LDAPAPIFeatureInfo features[] = {
43 #ifdef LDAP_API_FEATURE_X_OPENLDAP
44 	{	/* OpenLDAP Extensions API Feature */
45 		LDAP_FEATURE_INFO_VERSION,
46 		"X_OPENLDAP",
47 		LDAP_API_FEATURE_X_OPENLDAP
48 	},
49 #endif
50 
51 #ifdef LDAP_API_FEATURE_THREAD_SAFE
52 	{	/* Basic Thread Safe */
53 		LDAP_FEATURE_INFO_VERSION,
54 		"THREAD_SAFE",
55 		LDAP_API_FEATURE_THREAD_SAFE
56 	},
57 #endif
58 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
59 	{	/* Session Thread Safe */
60 		LDAP_FEATURE_INFO_VERSION,
61 		"SESSION_THREAD_SAFE",
62 		LDAP_API_FEATURE_SESSION_THREAD_SAFE
63 	},
64 #endif
65 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
66 	{	/* Operation Thread Safe */
67 		LDAP_FEATURE_INFO_VERSION,
68 		"OPERATION_THREAD_SAFE",
69 		LDAP_API_FEATURE_OPERATION_THREAD_SAFE
70 	},
71 #endif
72 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
73 	{	/* OpenLDAP Reentrant */
74 		LDAP_FEATURE_INFO_VERSION,
75 		"X_OPENLDAP_REENTRANT",
76 		LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
77 	},
78 #endif
79 #ifdef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
80 	{	/* OpenLDAP Thread Safe */
81 		LDAP_FEATURE_INFO_VERSION,
82 		"X_OPENLDAP_THREAD_SAFE",
83 		LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
84 	},
85 #endif
86 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
87 	{	/* V2 Referrals */
88 		LDAP_FEATURE_INFO_VERSION,
89 		"X_OPENLDAP_V2_REFERRALS",
90 		LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
91 	},
92 #endif
93 	{0, NULL, 0}
94 };
95 
96 int
ldap_get_option(LDAP * ld,int option,void * outvalue)97 ldap_get_option(
98 	LDAP	*ld,
99 	int		option,
100 	void	*outvalue)
101 {
102 	struct ldapoptions *lo;
103 	int rc = LDAP_OPT_ERROR;
104 
105 	/* Get pointer to global option structure */
106 	lo = LDAP_INT_GLOBAL_OPT();
107 	if (NULL == lo)	{
108 		return LDAP_NO_MEMORY;
109 	}
110 
111 	if( lo->ldo_valid != LDAP_INITIALIZED ) {
112 		ldap_int_initialize(lo, NULL);
113 		if ( lo->ldo_valid != LDAP_INITIALIZED )
114 			return LDAP_LOCAL_ERROR;
115 	}
116 
117 	if(ld != NULL) {
118 		if( !LDAP_VALID( ld ) ) {
119 			return LDAP_OPT_ERROR;
120 		}
121 
122 		lo = &ld->ld_options;
123 	}
124 
125 	if(outvalue == NULL) {
126 		/* no place to get to */
127 		return LDAP_OPT_ERROR;
128 	}
129 
130 	LDAP_MUTEX_LOCK( &lo->ldo_mutex );
131 
132 	switch(option) {
133 	case LDAP_OPT_API_INFO: {
134 			struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
135 
136 			if(info == NULL) {
137 				/* outvalue must point to an apiinfo structure */
138 				break;	/* LDAP_OPT_ERROR */
139 			}
140 
141 			if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
142 				/* api info version mismatch */
143 				info->ldapai_info_version = LDAP_API_INFO_VERSION;
144 				break;	/* LDAP_OPT_ERROR */
145 			}
146 
147 			info->ldapai_api_version = LDAP_API_VERSION;
148 			info->ldapai_protocol_version = LDAP_VERSION_MAX;
149 
150 			if(features[0].ldapaif_name == NULL) {
151 				info->ldapai_extensions = NULL;
152 			} else {
153 				int i;
154 				info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
155 					sizeof(features)/sizeof(LDAPAPIFeatureInfo));
156 				if ( info->ldapai_extensions == NULL ) {
157 					rc = LDAP_NO_MEMORY;
158 					break;
159 				}
160 
161 				for(i=0; features[i].ldapaif_name != NULL; i++) {
162 					info->ldapai_extensions[i] =
163 						LDAP_STRDUP(features[i].ldapaif_name);
164 					if ( info->ldapai_extensions[i] == NULL ) {
165 						rc = LDAP_NO_MEMORY;
166 						break;
167 					}
168 				}
169 				if ( features[i].ldapaif_name != NULL ) {
170 					break; /* LDAP_NO_MEMORY */
171 				}
172 
173 				info->ldapai_extensions[i] = NULL;
174 			}
175 
176 			info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
177 			info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
178 
179 			rc = LDAP_OPT_SUCCESS;
180 			break;
181 		} break;
182 
183 	case LDAP_OPT_DESC:
184 		if( ld == NULL || ld->ld_sb == NULL ) {
185 			/* bad param */
186 			break;
187 		}
188 
189 		ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
190 		rc = LDAP_OPT_SUCCESS;
191 		break;
192 
193 	case LDAP_OPT_SOCKBUF:
194 		if( ld == NULL ) break;
195 		*(Sockbuf **)outvalue = ld->ld_sb;
196 		rc = LDAP_OPT_SUCCESS;
197 		break;
198 
199 	case LDAP_OPT_TIMEOUT:
200 		/* the caller has to free outvalue ! */
201 		if ( lo->ldo_tm_api.tv_sec < 0 ) {
202 			*(void **)outvalue = NULL;
203 		} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
204 			break;	/* LDAP_OPT_ERROR */
205 		}
206 		rc = LDAP_OPT_SUCCESS;
207 		break;
208 
209 	case LDAP_OPT_NETWORK_TIMEOUT:
210 		/* the caller has to free outvalue ! */
211 		if ( lo->ldo_tm_net.tv_sec < 0 ) {
212 			*(void **)outvalue = NULL;
213 		} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
214 			break;	/* LDAP_OPT_ERROR */
215 		}
216 		rc = LDAP_OPT_SUCCESS;
217 		break;
218 
219 	case LDAP_OPT_DEREF:
220 		* (int *) outvalue = lo->ldo_deref;
221 		rc = LDAP_OPT_SUCCESS;
222 		break;
223 
224 	case LDAP_OPT_SIZELIMIT:
225 		* (int *) outvalue = lo->ldo_sizelimit;
226 		rc = LDAP_OPT_SUCCESS;
227 		break;
228 
229 	case LDAP_OPT_TIMELIMIT:
230 		* (int *) outvalue = lo->ldo_timelimit;
231 		rc = LDAP_OPT_SUCCESS;
232 		break;
233 
234 	case LDAP_OPT_REFERRALS:
235 		* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
236 		rc = LDAP_OPT_SUCCESS;
237 		break;
238 
239 	case LDAP_OPT_RESTART:
240 		* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
241 		rc = LDAP_OPT_SUCCESS;
242 		break;
243 
244 	case LDAP_OPT_PROTOCOL_VERSION:
245 		* (int *) outvalue = lo->ldo_version;
246 		rc = LDAP_OPT_SUCCESS;
247 		break;
248 
249 	case LDAP_OPT_SERVER_CONTROLS:
250 		* (LDAPControl ***) outvalue =
251 			ldap_controls_dup( lo->ldo_sctrls );
252 		rc = LDAP_OPT_SUCCESS;
253 		break;
254 
255 	case LDAP_OPT_CLIENT_CONTROLS:
256 		* (LDAPControl ***) outvalue =
257 			ldap_controls_dup( lo->ldo_cctrls );
258 		rc = LDAP_OPT_SUCCESS;
259 		break;
260 
261 	case LDAP_OPT_HOST_NAME:
262 		* (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
263 		rc = LDAP_OPT_SUCCESS;
264 		break;
265 
266 	case LDAP_OPT_SOCKET_BIND_ADDRESSES:
267 		if ( lo->ldo_local_ip_addrs.local_ip_addrs == NULL ) {
268 			* (void **) outvalue = NULL;
269 		}
270 		else {
271 			* (char **) outvalue =
272 				LDAP_STRDUP( lo->ldo_local_ip_addrs.local_ip_addrs );
273 		}
274 		rc = LDAP_OPT_SUCCESS;
275 		break;
276 
277 	case LDAP_OPT_URI:
278 		* (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
279 		rc = LDAP_OPT_SUCCESS;
280 		break;
281 
282 	case LDAP_OPT_DEFBASE:
283 		if( lo->ldo_defbase == NULL ) {
284 			* (char **) outvalue = NULL;
285 		} else {
286 			* (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
287 		}
288 		rc = LDAP_OPT_SUCCESS;
289 		break;
290 
291 	case LDAP_OPT_CONNECT_ASYNC:
292 		* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
293 		rc = LDAP_OPT_SUCCESS;
294 		break;
295 
296 	case LDAP_OPT_CONNECT_CB:
297 		{
298 			/* Getting deletes the specified callback */
299 			ldaplist **ll = &lo->ldo_conn_cbs;
300 			for (;*ll;ll = &(*ll)->ll_next) {
301 				if ((*ll)->ll_data == outvalue) {
302 					ldaplist *lc = *ll;
303 					*ll = lc->ll_next;
304 					LDAP_FREE(lc);
305 					break;
306 				}
307 			}
308 		}
309 		rc = LDAP_OPT_SUCCESS;
310 		break;
311 
312 	case LDAP_OPT_RESULT_CODE:
313 		if(ld == NULL) {
314 			/* bad param */
315 			break;
316 		}
317 		* (int *) outvalue = ld->ld_errno;
318 		rc = LDAP_OPT_SUCCESS;
319 		break;
320 
321 	case LDAP_OPT_DIAGNOSTIC_MESSAGE:
322 		if(ld == NULL) {
323 			/* bad param */
324 			break;
325 		}
326 
327 		if( ld->ld_error == NULL ) {
328 			* (char **) outvalue = NULL;
329 		} else {
330 			* (char **) outvalue = LDAP_STRDUP(ld->ld_error);
331 		}
332 		rc = LDAP_OPT_SUCCESS;
333 		break;
334 
335 	case LDAP_OPT_MATCHED_DN:
336 		if(ld == NULL) {
337 			/* bad param */
338 			break;
339 		}
340 
341 		if( ld->ld_matched == NULL ) {
342 			* (char **) outvalue = NULL;
343 		} else {
344 			* (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
345 		}
346 		rc = LDAP_OPT_SUCCESS;
347 		break;
348 
349 	case LDAP_OPT_REFERRAL_URLS:
350 		if(ld == NULL) {
351 			/* bad param */
352 			break;
353 		}
354 
355 		if( ld->ld_referrals == NULL ) {
356 			* (char ***) outvalue = NULL;
357 		} else {
358 			* (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
359 		}
360 		rc = LDAP_OPT_SUCCESS;
361 		break;
362 
363 	case LDAP_OPT_API_FEATURE_INFO: {
364 			LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
365 			int i;
366 
367 			if(info == NULL)
368 				break;	/* LDAP_OPT_ERROR */
369 
370 			if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
371 				/* api info version mismatch */
372 				info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
373 				break;	/* LDAP_OPT_ERROR */
374 			}
375 
376 			if(info->ldapaif_name == NULL)
377 				break;	/* LDAP_OPT_ERROR */
378 
379 			for(i=0; features[i].ldapaif_name != NULL; i++) {
380 				if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
381 					info->ldapaif_version =
382 						features[i].ldapaif_version;
383 					rc = LDAP_OPT_SUCCESS;
384 					break;
385 				}
386 			}
387 		}
388 		break;
389 
390 	case LDAP_OPT_DEBUG_LEVEL:
391 		* (int *) outvalue = lo->ldo_debug;
392 		rc = LDAP_OPT_SUCCESS;
393 		break;
394 
395 	case LDAP_OPT_SESSION_REFCNT:
396 		if(ld == NULL) {
397 			/* bad param */
398 			break;
399 		}
400 		LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
401 		* (int *) outvalue = ld->ld_ldcrefcnt;
402 		LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
403 		rc = LDAP_OPT_SUCCESS;
404 		break;
405 
406 	case LDAP_OPT_KEEPCONN:
407 		* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_KEEPCONN);
408 		rc = LDAP_OPT_SUCCESS;
409 		break;
410 
411 	case LDAP_OPT_X_KEEPALIVE_IDLE:
412 		* (int *) outvalue = lo->ldo_keepalive_idle;
413 		rc = LDAP_OPT_SUCCESS;
414 		break;
415 
416 	case LDAP_OPT_X_KEEPALIVE_PROBES:
417 		* (int *) outvalue = lo->ldo_keepalive_probes;
418 		rc = LDAP_OPT_SUCCESS;
419 		break;
420 
421 	case LDAP_OPT_X_KEEPALIVE_INTERVAL:
422 		* (int *) outvalue = lo->ldo_keepalive_interval;
423 		rc = LDAP_OPT_SUCCESS;
424 		break;
425 
426 	case LDAP_OPT_TCP_USER_TIMEOUT:
427 		* (unsigned int *) outvalue = lo->ldo_tcp_user_timeout;
428 		rc = LDAP_OPT_SUCCESS;
429 		break;
430 
431 	default:
432 #ifdef HAVE_TLS
433 		if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
434 			rc = LDAP_OPT_SUCCESS;
435 			break;
436 		}
437 #endif
438 #ifdef HAVE_CYRUS_SASL
439 		if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
440 			rc = LDAP_OPT_SUCCESS;
441 			break;
442 		}
443 #endif
444 #ifdef HAVE_GSSAPI
445 		if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
446 			rc = LDAP_OPT_SUCCESS;
447 			break;
448 		}
449 #endif
450 		/* bad param */
451 		break;
452 	}
453 
454 	LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
455 	return ( rc );
456 }
457 
458 int
ldap_set_option(LDAP * ld,int option,LDAP_CONST void * invalue)459 ldap_set_option(
460 	LDAP	*ld,
461 	int		option,
462 	LDAP_CONST void	*invalue)
463 {
464 	struct ldapoptions *lo;
465 	int *dbglvl = NULL;
466 	int rc = LDAP_OPT_ERROR;
467 
468 	/* Get pointer to global option structure */
469 	lo = LDAP_INT_GLOBAL_OPT();
470 	if (lo == NULL)	{
471 		return LDAP_NO_MEMORY;
472 	}
473 
474 	/*
475 	 * The architecture to turn on debugging has a chicken and egg
476 	 * problem. Thus, we introduce a fix here.
477 	 */
478 
479 	if (option == LDAP_OPT_DEBUG_LEVEL) {
480 		dbglvl = (int *) invalue;
481 	}
482 
483 	if( lo->ldo_valid != LDAP_INITIALIZED ) {
484 		ldap_int_initialize(lo, dbglvl);
485 		if ( lo->ldo_valid != LDAP_INITIALIZED )
486 			return LDAP_LOCAL_ERROR;
487 	}
488 
489 	if(ld != NULL) {
490 		assert( LDAP_VALID( ld ) );
491 
492 		if( !LDAP_VALID( ld ) ) {
493 			return LDAP_OPT_ERROR;
494 		}
495 
496 		lo = &ld->ld_options;
497 	}
498 
499 	LDAP_MUTEX_LOCK( &lo->ldo_mutex );
500 
501 	switch ( option ) {
502 
503 	/* options with boolean values */
504 	case LDAP_OPT_REFERRALS:
505 		if(invalue == LDAP_OPT_OFF) {
506 			LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
507 		} else {
508 			LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
509 		}
510 		rc = LDAP_OPT_SUCCESS;
511 		break;
512 
513 	case LDAP_OPT_RESTART:
514 		if(invalue == LDAP_OPT_OFF) {
515 			LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
516 		} else {
517 			LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
518 		}
519 		rc = LDAP_OPT_SUCCESS;
520 		break;
521 
522 	case LDAP_OPT_CONNECT_ASYNC:
523 		if(invalue == LDAP_OPT_OFF) {
524 			LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC);
525 		} else {
526 			LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
527 		}
528 		rc = LDAP_OPT_SUCCESS;
529 		break;
530 
531 	case LDAP_OPT_KEEPCONN:
532 		if(invalue == LDAP_OPT_OFF) {
533 			LDAP_BOOL_CLR(lo, LDAP_BOOL_KEEPCONN);
534 		} else {
535 			LDAP_BOOL_SET(lo, LDAP_BOOL_KEEPCONN);
536 		}
537 		rc = LDAP_OPT_SUCCESS;
538 		break;
539 	/* options which can withstand invalue == NULL */
540 	case LDAP_OPT_SERVER_CONTROLS: {
541 			LDAPControl *const *controls =
542 				(LDAPControl *const *) invalue;
543 
544 			if( lo->ldo_sctrls )
545 				ldap_controls_free( lo->ldo_sctrls );
546 
547 			if( controls == NULL || *controls == NULL ) {
548 				lo->ldo_sctrls = NULL;
549 				rc = LDAP_OPT_SUCCESS;
550 				break;
551 			}
552 
553 			lo->ldo_sctrls = ldap_controls_dup( controls );
554 
555 			if(lo->ldo_sctrls == NULL) {
556 				/* memory allocation error ? */
557 				break;	/* LDAP_OPT_ERROR */
558 			}
559 		}
560 		rc = LDAP_OPT_SUCCESS;
561 		break;
562 
563 	case LDAP_OPT_CLIENT_CONTROLS: {
564 			LDAPControl *const *controls =
565 				(LDAPControl *const *) invalue;
566 
567 			if( lo->ldo_cctrls )
568 				ldap_controls_free( lo->ldo_cctrls );
569 
570 			if( controls == NULL || *controls == NULL ) {
571 				lo->ldo_cctrls = NULL;
572 				rc = LDAP_OPT_SUCCESS;
573 				break;
574 			}
575 
576 			lo->ldo_cctrls = ldap_controls_dup( controls );
577 
578 			if(lo->ldo_cctrls == NULL) {
579 				/* memory allocation error ? */
580 				break;	/* LDAP_OPT_ERROR */
581 			}
582 		}
583 		rc = LDAP_OPT_SUCCESS;
584 		break;
585 
586 
587 	case LDAP_OPT_HOST_NAME: {
588 			const char *host = (const char *) invalue;
589 			LDAPURLDesc *ludlist = NULL;
590 			rc = LDAP_OPT_SUCCESS;
591 
592 			if(host != NULL) {
593 				rc = ldap_url_parsehosts( &ludlist, host,
594 					lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
595 
596 			} else if(ld == NULL) {
597 				/*
598 				 * must want global default returned
599 				 * to initial condition.
600 				 */
601 				rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
602 					LDAP_PVT_URL_PARSE_NOEMPTY_HOST
603 					| LDAP_PVT_URL_PARSE_DEF_PORT );
604 
605 			} else {
606 				/*
607 				 * must want the session default
608 				 *   updated to the current global default
609 				 */
610 				ludlist = ldap_url_duplist(
611 					ldap_int_global_options.ldo_defludp);
612 				if (ludlist == NULL)
613 					rc = LDAP_NO_MEMORY;
614 			}
615 
616 			if (rc == LDAP_OPT_SUCCESS) {
617 				if (lo->ldo_defludp != NULL)
618 					ldap_free_urllist(lo->ldo_defludp);
619 				lo->ldo_defludp = ludlist;
620 			}
621 			break;
622 		}
623 
624 	case LDAP_OPT_SOCKET_BIND_ADDRESSES: {
625 			const char *source_ip = (const char *) invalue;
626 			char **source_ip_lst = NULL;
627 
628 			ldapsourceip temp_source_ip;
629 			memset( &temp_source_ip, 0, sizeof( ldapsourceip ) );
630 			rc = LDAP_OPT_SUCCESS;
631 			if( source_ip == NULL ) {
632 				if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ) {
633 					LDAP_FREE( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs );
634 					memset( &ld->ld_options.ldo_local_ip_addrs, 0,
635 						sizeof( ldapsourceip ) );
636 				}
637 			}
638 			else {
639 				source_ip_lst = ldap_str2charray( source_ip, " " );
640 
641 				if ( source_ip_lst == NULL )
642 					rc =  LDAP_NO_MEMORY;
643 
644 				if( rc == LDAP_OPT_SUCCESS ) {
645 					rc = ldap_validate_and_fill_sourceip ( source_ip_lst,
646 						&temp_source_ip );
647 					ldap_charray_free( source_ip_lst );
648 				}
649 				if ( rc == LDAP_OPT_SUCCESS ) {
650 					if ( lo->ldo_local_ip_addrs.local_ip_addrs != NULL ) {
651 						LDAP_FREE( lo->ldo_local_ip_addrs.local_ip_addrs );
652 						lo->ldo_local_ip_addrs.local_ip_addrs = NULL;
653 					}
654 					lo->ldo_local_ip_addrs = temp_source_ip;
655 					lo->ldo_local_ip_addrs.local_ip_addrs = LDAP_STRDUP( source_ip );
656 				}
657 			}
658 			break;
659 		}
660 
661 	case LDAP_OPT_URI: {
662 			const char *urls = (const char *) invalue;
663 			LDAPURLDesc *ludlist = NULL;
664 			rc = LDAP_OPT_SUCCESS;
665 
666 			if(urls != NULL) {
667 				rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
668 					LDAP_PVT_URL_PARSE_NOEMPTY_HOST
669 					| LDAP_PVT_URL_PARSE_DEF_PORT );
670 			} else if(ld == NULL) {
671 				/*
672 				 * must want global default returned
673 				 * to initial condition.
674 				 */
675 				rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
676 					LDAP_PVT_URL_PARSE_NOEMPTY_HOST
677 					| LDAP_PVT_URL_PARSE_DEF_PORT );
678 
679 			} else {
680 				/*
681 				 * must want the session default
682 				 *   updated to the current global default
683 				 */
684 				ludlist = ldap_url_duplist(
685 					ldap_int_global_options.ldo_defludp);
686 				if (ludlist == NULL)
687 					rc = LDAP_URL_ERR_MEM;
688 			}
689 
690 			switch (rc) {
691 			case LDAP_URL_SUCCESS:		/* Success */
692 				rc = LDAP_SUCCESS;
693 				break;
694 
695 			case LDAP_URL_ERR_MEM:		/* can't allocate memory space */
696 				rc = LDAP_NO_MEMORY;
697 				break;
698 
699 			case LDAP_URL_ERR_PARAM:	/* parameter is bad */
700 			case LDAP_URL_ERR_BADSCHEME:	/* URL doesn't begin with "ldap[si]://" */
701 			case LDAP_URL_ERR_BADENCLOSURE:	/* URL is missing trailing ">" */
702 			case LDAP_URL_ERR_BADURL:	/* URL is bad */
703 			case LDAP_URL_ERR_BADHOST:	/* host port is bad */
704 			case LDAP_URL_ERR_BADATTRS:	/* bad (or missing) attributes */
705 			case LDAP_URL_ERR_BADSCOPE:	/* scope string is invalid (or missing) */
706 			case LDAP_URL_ERR_BADFILTER:	/* bad or missing filter */
707 			case LDAP_URL_ERR_BADEXTS:	/* bad or missing extensions */
708 				rc = LDAP_PARAM_ERROR;
709 				break;
710 			}
711 
712 			if (rc == LDAP_SUCCESS) {
713 				if (lo->ldo_defludp != NULL)
714 					ldap_free_urllist(lo->ldo_defludp);
715 				lo->ldo_defludp = ludlist;
716 			}
717 			break;
718 		}
719 
720 	case LDAP_OPT_DEFBASE: {
721 			const char *newbase = (const char *) invalue;
722 			char *defbase = NULL;
723 
724 			if ( newbase != NULL ) {
725 				defbase = LDAP_STRDUP( newbase );
726 				if ( defbase == NULL ) {
727 					rc = LDAP_NO_MEMORY;
728 					break;
729 				}
730 
731 			} else if ( ld != NULL ) {
732 				defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
733 				if ( defbase == NULL ) {
734 					rc = LDAP_NO_MEMORY;
735 					break;
736 				}
737 			}
738 
739 			if ( lo->ldo_defbase != NULL )
740 				LDAP_FREE( lo->ldo_defbase );
741 			lo->ldo_defbase = defbase;
742 		}
743 		rc = LDAP_OPT_SUCCESS;
744 		break;
745 
746 	case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
747 			const char *err = (const char *) invalue;
748 
749 			if(ld == NULL) {
750 				/* need a struct ldap */
751 				break;	/* LDAP_OPT_ERROR */
752 			}
753 
754 			if( ld->ld_error ) {
755 				LDAP_FREE(ld->ld_error);
756 				ld->ld_error = NULL;
757 			}
758 
759 			if ( err ) {
760 				ld->ld_error = LDAP_STRDUP(err);
761 			}
762 		}
763 		rc = LDAP_OPT_SUCCESS;
764 		break;
765 
766 	case LDAP_OPT_MATCHED_DN: {
767 			const char *matched = (const char *) invalue;
768 
769 			if (ld == NULL) {
770 				/* need a struct ldap */
771 				break;	/* LDAP_OPT_ERROR */
772 			}
773 
774 			if( ld->ld_matched ) {
775 				LDAP_FREE(ld->ld_matched);
776 				ld->ld_matched = NULL;
777 			}
778 
779 			if ( matched ) {
780 				ld->ld_matched = LDAP_STRDUP( matched );
781 			}
782 		}
783 		rc = LDAP_OPT_SUCCESS;
784 		break;
785 
786 	case LDAP_OPT_REFERRAL_URLS: {
787 			char *const *referrals = (char *const *) invalue;
788 
789 			if(ld == NULL) {
790 				/* need a struct ldap */
791 				break;	/* LDAP_OPT_ERROR */
792 			}
793 
794 			if( ld->ld_referrals ) {
795 				LDAP_VFREE(ld->ld_referrals);
796 			}
797 
798 			if ( referrals ) {
799 				ld->ld_referrals = ldap_value_dup(referrals);
800 			}
801 		}
802 		rc = LDAP_OPT_SUCCESS;
803 		break;
804 
805 	/* Only accessed from inside this function by ldap_set_rebind_proc() */
806 	case LDAP_OPT_REBIND_PROC: {
807 			lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
808 		}
809 		rc = LDAP_OPT_SUCCESS;
810 		break;
811 	case LDAP_OPT_REBIND_PARAMS: {
812 			lo->ldo_rebind_params = (void *)invalue;
813 		}
814 		rc = LDAP_OPT_SUCCESS;
815 		break;
816 
817 	/* Only accessed from inside this function by ldap_set_nextref_proc() */
818 	case LDAP_OPT_NEXTREF_PROC: {
819 			lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
820 		}
821 		rc = LDAP_OPT_SUCCESS;
822 		break;
823 	case LDAP_OPT_NEXTREF_PARAMS: {
824 			lo->ldo_nextref_params = (void *)invalue;
825 		}
826 		rc = LDAP_OPT_SUCCESS;
827 		break;
828 
829 	/* Only accessed from inside this function by ldap_set_urllist_proc() */
830 	case LDAP_OPT_URLLIST_PROC: {
831 			lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
832 		}
833 		rc = LDAP_OPT_SUCCESS;
834 		break;
835 	case LDAP_OPT_URLLIST_PARAMS: {
836 			lo->ldo_urllist_params = (void *)invalue;
837 		}
838 		rc = LDAP_OPT_SUCCESS;
839 		break;
840 
841 	/* read-only options */
842 	case LDAP_OPT_API_INFO:
843 	case LDAP_OPT_DESC:
844 	case LDAP_OPT_SOCKBUF:
845 	case LDAP_OPT_API_FEATURE_INFO:
846 		break;	/* LDAP_OPT_ERROR */
847 
848 	/* options which cannot withstand invalue == NULL */
849 	case LDAP_OPT_DEREF:
850 	case LDAP_OPT_SIZELIMIT:
851 	case LDAP_OPT_TIMELIMIT:
852 	case LDAP_OPT_PROTOCOL_VERSION:
853 	case LDAP_OPT_RESULT_CODE:
854 	case LDAP_OPT_DEBUG_LEVEL:
855 	case LDAP_OPT_TIMEOUT:
856 	case LDAP_OPT_NETWORK_TIMEOUT:
857 	case LDAP_OPT_CONNECT_CB:
858 	case LDAP_OPT_X_KEEPALIVE_IDLE:
859 	case LDAP_OPT_X_KEEPALIVE_PROBES :
860 	case LDAP_OPT_X_KEEPALIVE_INTERVAL :
861 	case LDAP_OPT_TCP_USER_TIMEOUT:
862 		if(invalue == NULL) {
863 			/* no place to set from */
864 			LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
865 			return ( LDAP_OPT_ERROR );
866 		}
867 		break;
868 
869 	default:
870 #ifdef HAVE_TLS
871 		if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) {
872 			LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
873 			return ( LDAP_OPT_SUCCESS );
874 		}
875 #endif
876 #ifdef HAVE_CYRUS_SASL
877 		if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) {
878 			LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
879 			return ( LDAP_OPT_SUCCESS );
880 		}
881 #endif
882 #ifdef HAVE_GSSAPI
883 		if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) {
884 			LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
885 			return ( LDAP_OPT_SUCCESS );
886 		}
887 #endif
888 		/* bad param */
889 		break;	/* LDAP_OPT_ERROR */
890 	}
891 
892 	/* options which cannot withstand invalue == NULL */
893 
894 	switch(option) {
895 	case LDAP_OPT_DEREF:
896 		/* FIXME: check value for protocol compliance? */
897 		lo->ldo_deref = * (const int *) invalue;
898 		rc = LDAP_OPT_SUCCESS;
899 		break;
900 
901 	case LDAP_OPT_SIZELIMIT:
902 		/* FIXME: check value for protocol compliance? */
903 		lo->ldo_sizelimit = * (const int *) invalue;
904 		rc = LDAP_OPT_SUCCESS;
905 		break;
906 
907 	case LDAP_OPT_TIMELIMIT:
908 		/* FIXME: check value for protocol compliance? */
909 		lo->ldo_timelimit = * (const int *) invalue;
910 		rc = LDAP_OPT_SUCCESS;
911 		break;
912 
913 	case LDAP_OPT_TIMEOUT: {
914 			const struct timeval *tv =
915 				(const struct timeval *) invalue;
916 
917 			lo->ldo_tm_api = *tv;
918 		}
919 		rc = LDAP_OPT_SUCCESS;
920 		break;
921 
922 	case LDAP_OPT_NETWORK_TIMEOUT: {
923 			const struct timeval *tv =
924 				(const struct timeval *) invalue;
925 
926 			lo->ldo_tm_net = *tv;
927 		}
928 		rc = LDAP_OPT_SUCCESS;
929 		break;
930 
931 	case LDAP_OPT_PROTOCOL_VERSION: {
932 			int vers = * (const int *) invalue;
933 			if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
934 				/* not supported */
935 				break;
936 			}
937 			lo->ldo_version = vers;
938 		}
939 		rc = LDAP_OPT_SUCCESS;
940 		break;
941 
942 	case LDAP_OPT_RESULT_CODE: {
943 			int err = * (const int *) invalue;
944 
945 			if(ld == NULL) {
946 				/* need a struct ldap */
947 				break;
948 			}
949 
950 			ld->ld_errno = err;
951 		}
952 		rc = LDAP_OPT_SUCCESS;
953 		break;
954 
955 	case LDAP_OPT_DEBUG_LEVEL:
956 		lo->ldo_debug = * (const int *) invalue;
957 		rc = LDAP_OPT_SUCCESS;
958 		break;
959 
960 	case LDAP_OPT_CONNECT_CB:
961 		{
962 			/* setting pushes the callback */
963 			ldaplist *ll;
964 			ll = LDAP_MALLOC( sizeof( *ll ));
965 			if ( ll == NULL ) {
966 				rc = LDAP_NO_MEMORY;
967 				break;
968 			}
969 
970 			ll->ll_data = (void *)invalue;
971 			ll->ll_next = lo->ldo_conn_cbs;
972 			lo->ldo_conn_cbs = ll;
973 		}
974 		rc = LDAP_OPT_SUCCESS;
975 		break;
976 	case LDAP_OPT_X_KEEPALIVE_IDLE:
977 		lo->ldo_keepalive_idle = * (const int *) invalue;
978 		rc = LDAP_OPT_SUCCESS;
979 		break;
980 	case LDAP_OPT_X_KEEPALIVE_PROBES :
981 		lo->ldo_keepalive_probes = * (const int *) invalue;
982 		rc = LDAP_OPT_SUCCESS;
983 		break;
984 	case LDAP_OPT_X_KEEPALIVE_INTERVAL :
985 		lo->ldo_keepalive_interval = * (const int *) invalue;
986 		rc = LDAP_OPT_SUCCESS;
987 		break;
988 	case LDAP_OPT_TCP_USER_TIMEOUT:
989 		lo->ldo_tcp_user_timeout = * (const unsigned int *) invalue;
990 		rc = LDAP_OPT_SUCCESS;
991 		break;
992 
993 	}
994 	LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
995 	return ( rc );
996 }
997 
998 int
ldap_set_rebind_proc(LDAP * ld,LDAP_REBIND_PROC * proc,void * params)999 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
1000 {
1001 	int rc;
1002 	rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
1003 	if( rc != LDAP_OPT_SUCCESS ) return rc;
1004 
1005 	rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
1006 	return rc;
1007 }
1008 
1009 int
ldap_set_nextref_proc(LDAP * ld,LDAP_NEXTREF_PROC * proc,void * params)1010 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
1011 {
1012 	int rc;
1013 	rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
1014 	if( rc != LDAP_OPT_SUCCESS ) return rc;
1015 
1016 	rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
1017 	return rc;
1018 }
1019 
1020 int
ldap_set_urllist_proc(LDAP * ld,LDAP_URLLIST_PROC * proc,void * params)1021 ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
1022 {
1023 	int rc;
1024 	rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
1025 	if( rc != LDAP_OPT_SUCCESS ) return rc;
1026 
1027 	rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
1028 	return rc;
1029 }
1030