1 /*
2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * The contents of this file are subject to the Netscape Public
10 * License Version 1.1 (the "License"); you may not use this file
11 * except in compliance with the License. You may obtain a copy of
12 * the License at http://www.mozilla.org/NPL/
13 *
14 * Software distributed under the License is distributed on an "AS
15 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16 * implied. See the License for the specific language governing
17 * rights and limitations under the License.
18 *
19 * The Original Code is Mozilla Communicator client code, released
20 * March 31, 1998.
21 *
22 * The Initial Developer of the Original Code is Netscape
23 * Communications Corporation. Portions created by Netscape are
24 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25 * Rights Reserved.
26 *
27 * Contributor(s):
28 */
29 /*
30 * setoption.c - ldap_set_option implementation
31 */
32
33 #include "ldap-int.h"
34 #ifdef _SOLARIS_SDK
35 #include "solaris-priv.h"
36 #endif
37
38 extern int nsldapi_sasl_secprops(const char *in,
39 sasl_security_properties_t *secprops);
40
41 #define LDAP_SETCLR_BITOPT(ld, bit, optdata) \
42 if (optdata != NULL) { \
43 (ld)->ld_options |= bit; \
44 } else { \
45 (ld)->ld_options &= ~bit; \
46 }
47
48
49 int
50 LDAP_CALL
ldap_set_option(LDAP * ld,int option,const void * optdata)51 ldap_set_option(LDAP *ld, int option, const void *optdata)
52 {
53 int rc, i;
54 char *matched, *errstr;
55
56 if (!nsldapi_initialized) {
57 nsldapi_initialize_defaults();
58 }
59
60 /*
61 * process global options (not associated with an LDAP session handle)
62 */
63 if (option == LDAP_OPT_MEMALLOC_FN_PTRS) {
64 struct lber_memalloc_fns memalloc_fns;
65
66 /* set libldap ones via a struct copy */
67 nsldapi_memalloc_fns = *((struct ldap_memalloc_fns *)optdata);
68
69 /* also set liblber memory allocation callbacks */
70 memalloc_fns.lbermem_malloc =
71 nsldapi_memalloc_fns.ldapmem_malloc;
72 memalloc_fns.lbermem_calloc =
73 nsldapi_memalloc_fns.ldapmem_calloc;
74 memalloc_fns.lbermem_realloc =
75 nsldapi_memalloc_fns.ldapmem_realloc;
76 memalloc_fns.lbermem_free =
77 nsldapi_memalloc_fns.ldapmem_free;
78 if (ber_set_option(NULL, LBER_OPT_MEMALLOC_FN_PTRS,
79 &memalloc_fns) != 0) {
80 return (-1);
81 }
82
83 return (0);
84 }
85 /*
86 * LDAP_OPT_DEBUG_LEVEL is global
87 */
88 if (LDAP_OPT_DEBUG_LEVEL == option) {
89 #ifdef LDAP_DEBUG
90 ldap_debug = *((int *)optdata);
91 #endif
92 return (0);
93 }
94
95 /*
96 * if ld is NULL, arrange to modify our default settings
97 */
98 if (ld == NULL) {
99 ld = &nsldapi_ld_defaults;
100 #ifdef LDAP_DEBUG
101 ldap_debug = 0;
102 #endif
103
104 }
105
106 /*
107 * process options that are associated with an LDAP session handle
108 */
109 if (!NSLDAPI_VALID_LDAP_POINTER(ld)) {
110 return (-1); /* punt */
111 }
112
113 rc = 0;
114 if (ld != &nsldapi_ld_defaults &&
115 option != LDAP_OPT_EXTRA_THREAD_FN_PTRS &&
116 option != LDAP_OPT_THREAD_FN_PTRS) {
117 LDAP_MUTEX_LOCK(ld, LDAP_OPTION_LOCK);
118 }
119 switch (option) {
120 /* options that can be turned on and off */
121 #ifdef LDAP_DNS
122 case LDAP_OPT_DNS:
123 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_DNS, optdata);
124 break;
125 #endif
126
127 case LDAP_OPT_REFERRALS:
128 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_REFERRALS, optdata);
129 break;
130
131 #ifdef LDAP_SSLIO_HOOKS
132 case LDAP_OPT_SSL:
133 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_SSL, optdata);
134 break;
135 #endif
136
137 case LDAP_OPT_RESTART:
138 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_RESTART, optdata);
139 break;
140
141 case LDAP_OPT_RECONNECT:
142 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_RECONNECT, optdata);
143 break;
144
145 #ifdef LDAP_ASYNC_IO
146 case LDAP_OPT_ASYNC_CONNECT:
147 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_ASYNC, optdata);
148 break;
149 #endif /* LDAP_ASYNC_IO */
150
151 /* fields in the LDAP structure */
152 case LDAP_OPT_DEREF:
153 ld->ld_deref = *((int *)optdata);
154 break;
155 case LDAP_OPT_SIZELIMIT:
156 ld->ld_sizelimit = *((int *)optdata);
157 break;
158 case LDAP_OPT_TIMELIMIT:
159 ld->ld_timelimit = *((int *)optdata);
160 break;
161 case LDAP_OPT_REFERRAL_HOP_LIMIT:
162 ld->ld_refhoplimit = *((int *)optdata);
163 break;
164 case LDAP_OPT_PROTOCOL_VERSION:
165 ld->ld_version = *((int *)optdata);
166 if (ld->ld_defconn != NULL) { /* also set in default conn. */
167 ld->ld_defconn->lconn_version = ld->ld_version;
168 }
169 break;
170 case LDAP_OPT_SERVER_CONTROLS:
171 /* nsldapi_dup_controls returns -1 and sets lderrno on error */
172 rc = nsldapi_dup_controls(ld, &ld->ld_servercontrols,
173 (LDAPControl **)optdata);
174 break;
175 case LDAP_OPT_CLIENT_CONTROLS:
176 /* nsldapi_dup_controls returns -1 and sets lderrno on error */
177 rc = nsldapi_dup_controls(ld, &ld->ld_clientcontrols,
178 (LDAPControl **)optdata);
179 break;
180
181 /* rebind proc */
182 case LDAP_OPT_REBIND_FN:
183 ld->ld_rebind_fn = (LDAP_REBINDPROC_CALLBACK *) optdata;
184 break;
185 case LDAP_OPT_REBIND_ARG:
186 ld->ld_rebind_arg = (void *) optdata;
187 break;
188
189 #ifdef LDAP_SSLIO_HOOKS
190 /* i/o function pointers */
191 case LDAP_OPT_IO_FN_PTRS:
192 if ((rc = nsldapi_install_compat_io_fns(ld,
193 (struct ldap_io_fns *)optdata)) != LDAP_SUCCESS) {
194 LDAP_SET_LDERRNO(ld, rc, NULL, NULL);
195 rc = -1;
196 }
197 break;
198
199 /* extended i/o function pointers */
200 case LDAP_X_OPT_EXTIO_FN_PTRS:
201 /* denotes use of old iofns struct (no writev) */
202 if (((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_size ==
203 LDAP_X_EXTIO_FNS_SIZE_REV0) {
204 ld->ld_extio_size = LDAP_X_EXTIO_FNS_SIZE;
205 ld->ld_extclose_fn =
206 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_close;
207 ld->ld_extconnect_fn =
208 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_connect;
209 ld->ld_extread_fn =
210 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_read;
211 ld->ld_extwrite_fn =
212 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_write;
213 ld->ld_extpoll_fn =
214 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_poll;
215 ld->ld_extnewhandle_fn =
216 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_newhandle;
217 ld->ld_extdisposehandle_fn =
218 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->
219 lextiof_disposehandle;
220 ld->ld_ext_session_arg =
221 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_session_arg;
222 ld->ld_extwritev_fn = NULL;
223 if (ber_sockbuf_set_option(ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS,
224 &(ld->ld_ext_io_fns)) != 0) {
225 return (LDAP_LOCAL_ERROR);
226 }
227 } else {
228 /* struct copy */
229 ld->ld_ext_io_fns = *((struct ldap_x_ext_io_fns *)optdata);
230 }
231 if ((rc = nsldapi_install_lber_extiofns(ld, ld->ld_sbp))
232 != LDAP_SUCCESS) {
233 LDAP_SET_LDERRNO(ld, rc, NULL, NULL);
234 rc = -1;
235 }
236 break;
237 #endif
238
239 /* thread function pointers */
240 case LDAP_OPT_THREAD_FN_PTRS:
241 /*
242 * It is only safe to set the thread function pointers
243 * when one thread is using the LDAP session handle.
244 */
245 /* free existing mutexes (some are allocated by ldap_init()) */
246 nsldapi_mutex_free_all(ld);
247
248 /* struct copy */
249 ld->ld_thread = *((struct ldap_thread_fns *)optdata);
250
251 /* allocate new mutexes */
252 nsldapi_mutex_alloc_all(ld);
253
254 /* LDAP_OPTION_LOCK was never locked... so just return */
255 return (rc);
256
257 /* extra thread function pointers */
258 case LDAP_OPT_EXTRA_THREAD_FN_PTRS:
259 /* The extra thread funcs will only pick up the threadid */
260 ld->ld_thread2 = *((struct ldap_extra_thread_fns *)optdata);
261
262 /* Reset the rest of the structure preserving the threadid fn */
263 ld->ld_mutex_trylock_fn = (LDAP_TF_MUTEX_TRYLOCK_CALLBACK *)NULL;
264 ld->ld_sema_alloc_fn = (LDAP_TF_SEMA_ALLOC_CALLBACK *) NULL;
265 ld->ld_sema_free_fn = (LDAP_TF_SEMA_FREE_CALLBACK *) NULL;
266 ld->ld_sema_wait_fn = (LDAP_TF_SEMA_WAIT_CALLBACK *) NULL;
267 ld->ld_sema_post_fn = (LDAP_TF_SEMA_POST_CALLBACK *) NULL;
268
269 /* We assume that only one thread is active when replacing */
270 /* the threadid function. We will now proceed and reset all */
271 /* of the threadid/refcounts */
272 for (i = 0; i < LDAP_MAX_LOCK; i++) {
273 ld->ld_mutex_threadid[i] = (void *) -1;
274 ld->ld_mutex_refcnt[i] = 0;
275 }
276
277 return (rc);
278
279 /* DNS function pointers */
280 case LDAP_OPT_DNS_FN_PTRS:
281 /* struct copy */
282 ld->ld_dnsfn = *((struct ldap_dns_fns *)optdata);
283 break;
284
285 /* cache function pointers */
286 case LDAP_OPT_CACHE_FN_PTRS:
287 /* struct copy */
288 ld->ld_cache = *((struct ldap_cache_fns *)optdata);
289 break;
290 case LDAP_OPT_CACHE_STRATEGY:
291 ld->ld_cache_strategy = *((int *)optdata);
292 break;
293 case LDAP_OPT_CACHE_ENABLE:
294 ld->ld_cache_on = *((int *)optdata);
295 break;
296
297 case LDAP_OPT_ERROR_NUMBER:
298 LDAP_GET_LDERRNO(ld, &matched, &errstr);
299 matched = nsldapi_strdup(matched);
300 errstr = nsldapi_strdup(errstr);
301 LDAP_SET_LDERRNO(ld, *((int *)optdata), matched, errstr);
302 break;
303
304 case LDAP_OPT_ERROR_STRING:
305 rc = LDAP_GET_LDERRNO(ld, &matched, NULL);
306 matched = nsldapi_strdup(matched);
307 LDAP_SET_LDERRNO(ld, rc, matched,
308 nsldapi_strdup((char *)optdata));
309 rc = LDAP_SUCCESS;
310 break;
311
312 case LDAP_OPT_MATCHED_DN:
313 rc = LDAP_GET_LDERRNO(ld, NULL, &errstr);
314 errstr = nsldapi_strdup(errstr);
315 LDAP_SET_LDERRNO(ld, rc,
316 nsldapi_strdup((char *)optdata), errstr);
317 rc = LDAP_SUCCESS;
318 break;
319
320 case LDAP_OPT_PREFERRED_LANGUAGE:
321 if (NULL != ld->ld_preferred_language) {
322 NSLDAPI_FREE(ld->ld_preferred_language);
323 }
324 ld->ld_preferred_language = nsldapi_strdup((char *)optdata);
325 break;
326
327 case LDAP_OPT_HOST_NAME:
328 if (NULL != ld->ld_defhost) {
329 NSLDAPI_FREE(ld->ld_defhost);
330 }
331 ld->ld_defhost = nsldapi_strdup((char *)optdata);
332 break;
333
334 case LDAP_X_OPT_CONNECT_TIMEOUT:
335 ld->ld_connect_timeout = *((int *)optdata);
336 break;
337
338 #ifdef _SOLARIS_SDK
339 /* recursion prevention dns functions */
340 case LDAP_X_OPT_DNS_SKIPDB:
341 rc = prldap_x_install_dns_skipdb(ld, (const char *)optdata);
342 break;
343 #endif
344 #ifdef LDAP_SASLIO_HOOKS
345 /* SASL options */
346 case LDAP_OPT_X_SASL_MECH:
347 if (NULL != ld->ld_def_sasl_mech) {
348
349 NSLDAPI_FREE(ld->ld_def_sasl_mech);
350 }
351 ld->ld_def_sasl_mech = nsldapi_strdup((char *)optdata);
352 break;
353 case LDAP_OPT_X_SASL_REALM:
354 if (NULL != ld->ld_def_sasl_realm) {
355 NSLDAPI_FREE(ld->ld_def_sasl_realm);
356 }
357 ld->ld_def_sasl_realm = nsldapi_strdup((char *)optdata);
358 break;
359 case LDAP_OPT_X_SASL_AUTHCID:
360 if (NULL != ld->ld_def_sasl_authcid) {
361 NSLDAPI_FREE(ld->ld_def_sasl_authcid);
362 }
363 ld->ld_def_sasl_authcid = nsldapi_strdup((char *)optdata);
364 break;
365 case LDAP_OPT_X_SASL_AUTHZID:
366 if (NULL != ld->ld_def_sasl_authzid) {
367 NSLDAPI_FREE(ld->ld_def_sasl_authzid);
368 }
369 ld->ld_def_sasl_authzid = nsldapi_strdup((char *)optdata);
370 break;
371 case LDAP_OPT_X_SASL_SSF_EXTERNAL:
372 {
373 int sc;
374 sasl_ssf_t extprops;
375 sasl_conn_t *ctx;
376 if (ld->ld_defconn == NULL ||
377 ld->ld_defconn->lconn_sb == NULL) {
378 return (-1);
379 }
380 ctx = (sasl_conn_t *)
381 (ld->ld_defconn->lconn_sb->sb_sasl_ctx);
382 if (ctx == NULL) {
383 return (-1);
384 }
385 memset(&extprops, 0L, sizeof (extprops));
386 extprops = * ((sasl_ssf_t *)optdata);
387 sc = sasl_setprop(ctx, SASL_SSF_EXTERNAL,
388 (void *) &extprops);
389 if (sc != SASL_OK) {
390 return (-1);
391 }
392 }
393 break;
394 case LDAP_OPT_X_SASL_SECPROPS:
395 {
396 int sc;
397 sc = nsldapi_sasl_secprops((char *)optdata,
398 &ld->ld_sasl_secprops);
399 return (sc == LDAP_SUCCESS ? 0 : -1);
400 }
401 case LDAP_OPT_X_SASL_SSF_MIN:
402 ld->ld_sasl_secprops.min_ssf = *((sasl_ssf_t *)optdata);
403 break;
404 case LDAP_OPT_X_SASL_SSF_MAX:
405 ld->ld_sasl_secprops.max_ssf = *((sasl_ssf_t *)optdata);
406 break;
407 case LDAP_OPT_X_SASL_MAXBUFSIZE:
408 ld->ld_sasl_secprops.maxbufsize = *((sasl_ssf_t *)optdata);
409 break;
410 case LDAP_OPT_X_SASL_SSF: /* read only */
411 LDAP_SET_LDERRNO(ld, LDAP_PARAM_ERROR, NULL, NULL);
412 rc = -1;
413 break;
414 #endif
415
416 default:
417 LDAP_SET_LDERRNO(ld, LDAP_PARAM_ERROR, NULL, NULL);
418 rc = -1;
419 }
420
421 if (ld != &nsldapi_ld_defaults) {
422 LDAP_MUTEX_UNLOCK(ld, LDAP_OPTION_LOCK);
423 }
424 return (rc);
425 }
426