1 /*
2 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * The contents of this file are subject to the Netscape Public
8 * License Version 1.1 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.mozilla.org/NPL/
11 *
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
16 *
17 * The Original Code is Mozilla Communicator client code, released
18 * March 31, 1998.
19 *
20 * The Initial Developer of the Original Code is Netscape
21 * Communications Corporation. Portions created by Netscape are
22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
23 * Rights Reserved.
24 *
25 * Contributor(s):
26 */
27 #include "ldap-int.h"
28
29 #define LDAP_GET_BITOPT( ld, bit ) \
30 ((ld)->ld_options & bit ) != 0 ? 1 : 0
31
32 static int nsldapi_get_api_info( LDAPAPIInfo *aip );
33 static int nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip );
34
35
36 int
37 LDAP_CALL
ldap_get_option(LDAP * ld,int option,void * optdata)38 ldap_get_option( LDAP *ld, int option, void *optdata )
39 {
40 int rc = 0;
41
42 if ( !nsldapi_initialized ) {
43 nsldapi_initialize_defaults();
44 }
45
46 /*
47 * optdata MUST be a valid pointer...
48 */
49 if (NULL == optdata)
50 {
51 return(LDAP_PARAM_ERROR);
52 }
53 /*
54 * process global options (not associated with an LDAP session handle)
55 */
56 if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) {
57 /* struct copy */
58 *((struct ldap_memalloc_fns *)optdata) = nsldapi_memalloc_fns;
59 return( 0 );
60 }
61
62 if ( option == LDAP_OPT_API_INFO ) {
63 rc = nsldapi_get_api_info( (LDAPAPIInfo *)optdata );
64 if ( rc != LDAP_SUCCESS ) {
65 if ( ld != NULL ) {
66 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
67 }
68 return( -1 );
69 }
70 return( 0 );
71 }
72 /*
73 * LDAP_OPT_DEBUG_LEVEL is global
74 */
75 if (LDAP_OPT_DEBUG_LEVEL == option)
76 {
77 #ifdef LDAP_DEBUG
78 *((int *) optdata) = ldap_debug;
79 #endif /* LDAP_DEBUG */
80 return ( 0 );
81 }
82
83 /*
84 * if ld is NULL, arrange to return options from our default settings
85 */
86 if ( ld == NULL ) {
87 ld = &nsldapi_ld_defaults;
88 }
89
90 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
91 return( -1 ); /* punt */
92 }
93
94
95 if (ld != &nsldapi_ld_defaults)
96 LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK );
97 switch( option ) {
98 #ifdef LDAP_DNS
99 case LDAP_OPT_DNS:
100 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_DNS );
101 break;
102 #endif
103
104 case LDAP_OPT_REFERRALS:
105 *((int *) optdata) =
106 LDAP_GET_BITOPT( ld, LDAP_BITOPT_REFERRALS );
107 break;
108
109 #ifdef LDAP_SSLIO_HOOKS
110 case LDAP_OPT_SSL:
111 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_SSL );
112 break;
113 #endif
114 case LDAP_OPT_RESTART:
115 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_RESTART );
116 break;
117
118 case LDAP_OPT_RECONNECT:
119 *((int *) optdata) =
120 LDAP_GET_BITOPT( ld, LDAP_BITOPT_RECONNECT );
121 break;
122
123 #ifdef LDAP_ASYNC_IO
124 case LDAP_OPT_ASYNC_CONNECT:
125 *((int *) optdata) =
126 LDAP_GET_BITOPT( ld, LDAP_BITOPT_ASYNC );
127 break;
128 #endif /* LDAP_ASYNC_IO */
129
130 /* stuff in the sockbuf */
131 case LDAP_X_OPT_SOCKBUF:
132 *((Sockbuf **) optdata) = ld->ld_sbp;
133 break;
134 case LDAP_OPT_DESC:
135 if ( ber_sockbuf_get_option( ld->ld_sbp,
136 LBER_SOCKBUF_OPT_DESC, optdata ) != 0 ) {
137 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
138 rc = -1;
139 }
140 break;
141
142 /* fields in the LDAP structure */
143 case LDAP_OPT_DEREF:
144 *((int *) optdata) = ld->ld_deref;
145 break;
146 case LDAP_OPT_SIZELIMIT:
147 *((int *) optdata) = ld->ld_sizelimit;
148 break;
149 case LDAP_OPT_TIMELIMIT:
150 *((int *) optdata) = ld->ld_timelimit;
151 break;
152 case LDAP_OPT_REFERRAL_HOP_LIMIT:
153 *((int *) optdata) = ld->ld_refhoplimit;
154 break;
155 case LDAP_OPT_PROTOCOL_VERSION:
156 *((int *) optdata) = ld->ld_version;
157 break;
158 case LDAP_OPT_SERVER_CONTROLS:
159 /* fall through */
160 case LDAP_OPT_CLIENT_CONTROLS:
161 *((LDAPControl ***)optdata) = NULL;
162 /* nsldapi_dup_controls returns -1 and sets lderrno on error */
163 rc = nsldapi_dup_controls( ld, (LDAPControl ***)optdata,
164 ( option == LDAP_OPT_SERVER_CONTROLS ) ?
165 ld->ld_servercontrols : ld->ld_clientcontrols );
166 break;
167
168 /* rebind proc */
169 case LDAP_OPT_REBIND_FN:
170 *((LDAP_REBINDPROC_CALLBACK **) optdata) = ld->ld_rebind_fn;
171 break;
172 case LDAP_OPT_REBIND_ARG:
173 *((void **) optdata) = ld->ld_rebind_arg;
174 break;
175
176 #ifdef LDAP_SSLIO_HOOKS
177 /* i/o function pointers */
178 case LDAP_OPT_IO_FN_PTRS:
179 if ( ld->ld_io_fns_ptr == NULL ) {
180 memset( optdata, 0, sizeof( struct ldap_io_fns ));
181 } else {
182 /* struct copy */
183 *((struct ldap_io_fns *)optdata) = *(ld->ld_io_fns_ptr);
184 }
185 break;
186
187 /* extended i/o function pointers */
188 case LDAP_X_OPT_EXTIO_FN_PTRS:
189 if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) {
190 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close = ld->ld_extclose_fn;
191 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect = ld->ld_extconnect_fn;
192 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read = ld->ld_extread_fn;
193 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write = ld->ld_extwrite_fn;
194 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll = ld->ld_extpoll_fn;
195 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle = ld->ld_extnewhandle_fn;
196 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle = ld->ld_extdisposehandle_fn;
197 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg = ld->ld_ext_session_arg;
198 } else if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size ==
199 LDAP_X_EXTIO_FNS_SIZE ) {
200 /* struct copy */
201 *((struct ldap_x_ext_io_fns *) optdata) = ld->ld_ext_io_fns;
202 } else {
203 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
204 rc = -1;
205 }
206 break;
207 #endif /* LDAP_SSLIO_HOOKS */
208
209 /* thread function pointers */
210 case LDAP_OPT_THREAD_FN_PTRS:
211 /* struct copy */
212 *((struct ldap_thread_fns *) optdata) = ld->ld_thread;
213 break;
214
215 /* DNS function pointers */
216 case LDAP_OPT_DNS_FN_PTRS:
217 /* struct copy */
218 *((struct ldap_dns_fns *) optdata) = ld->ld_dnsfn;
219 break;
220
221 /* cache function pointers */
222 case LDAP_OPT_CACHE_FN_PTRS:
223 /* struct copy */
224 *((struct ldap_cache_fns *) optdata) = ld->ld_cache;
225 break;
226 case LDAP_OPT_CACHE_STRATEGY:
227 *((int *) optdata) = ld->ld_cache_strategy;
228 break;
229 case LDAP_OPT_CACHE_ENABLE:
230 *((int *) optdata) = ld->ld_cache_on;
231 break;
232
233 case LDAP_OPT_ERROR_NUMBER:
234 *((int *) optdata) = LDAP_GET_LDERRNO( ld, NULL, NULL );
235 break;
236
237 case LDAP_OPT_ERROR_STRING:
238 (void)LDAP_GET_LDERRNO( ld, NULL, (char **)optdata );
239 *((char **) optdata) = nsldapi_strdup( *((char **) optdata ));
240 break;
241
242 case LDAP_OPT_MATCHED_DN:
243 (void)LDAP_GET_LDERRNO( ld, (char **)optdata, NULL );
244 *((char **) optdata) = nsldapi_strdup( *((char **) optdata ));
245 break;
246
247 case LDAP_OPT_PREFERRED_LANGUAGE:
248 if ( NULL != ld->ld_preferred_language ) {
249 *((char **) optdata) =
250 nsldapi_strdup(ld->ld_preferred_language);
251 } else {
252 *((char **) optdata) = NULL;
253 }
254 break;
255
256 case LDAP_OPT_API_FEATURE_INFO:
257 rc = nsldapi_get_feature_info( (LDAPAPIFeatureInfo *)optdata );
258 if ( rc != LDAP_SUCCESS ) {
259 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
260 rc = -1;
261 }
262 break;
263
264 case LDAP_OPT_HOST_NAME:
265 *((char **) optdata) = nsldapi_strdup( ld->ld_defhost );
266 break;
267
268 case LDAP_X_OPT_CONNECT_TIMEOUT:
269 *((int *) optdata) = ld->ld_connect_timeout;
270 break;
271
272 #ifdef LDAP_SASLIO_HOOKS
273 /* SASL options */
274 case LDAP_OPT_X_SASL_MECH:
275 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_mech);
276 break;
277 case LDAP_OPT_X_SASL_REALM:
278 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_realm);
279 break;
280 case LDAP_OPT_X_SASL_AUTHCID:
281 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authcid);
282 break;
283 case LDAP_OPT_X_SASL_AUTHZID:
284 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authzid);
285 break;
286 case LDAP_OPT_X_SASL_SSF:
287 {
288 int sc;
289 sasl_ssf_t *ssf;
290 sasl_conn_t *ctx;
291 if( ld->ld_defconn == NULL ||
292 ld->ld_defconn->lconn_sb == NULL ) {
293 return -1;
294 }
295 ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sb->sb_sasl_ctx);
296 if ( ctx == NULL ) {
297 return -1;
298 }
299 sc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf );
300 if ( sc != SASL_OK ) {
301 return -1;
302 }
303 *((sasl_ssf_t *) optdata) = *ssf;
304 }
305 break;
306 case LDAP_OPT_X_SASL_SSF_MIN:
307 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.min_ssf;
308 break;
309 case LDAP_OPT_X_SASL_SSF_MAX:
310 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.max_ssf;
311 break;
312 case LDAP_OPT_X_SASL_MAXBUFSIZE:
313 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.maxbufsize;
314 break;
315 case LDAP_OPT_X_SASL_SSF_EXTERNAL:
316 case LDAP_OPT_X_SASL_SECPROPS:
317 /*
318 * These options are write only. Making these options
319 * read/write would expose semi-private interfaces of libsasl
320 * for which there are no cross platform/standardized
321 * definitions.
322 */
323 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
324 rc = -1;
325 break;
326 #endif
327
328 default:
329 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
330 rc = -1;
331 }
332 if (ld != &nsldapi_ld_defaults)
333 LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK );
334 return( rc );
335 }
336
337
338 /*
339 * Table of extended API features we support.
340 * The first field is the version of the info. strcuture itself; we do not
341 * use the ones from this table so it is okay to leave as zero.
342 */
343 static LDAPAPIFeatureInfo nsldapi_extensions[] = {
344 { 0, "SERVER_SIDE_SORT", LDAP_API_FEATURE_SERVER_SIDE_SORT },
345 { 0, "VIRTUAL_LIST_VIEW", LDAP_API_FEATURE_VIRTUAL_LIST_VIEW },
346 { 0, "PERSISTENT_SEARCH", LDAP_API_FEATURE_PERSISTENT_SEARCH },
347 { 0, "PROXY_AUTHORIZATION", LDAP_API_FEATURE_PROXY_AUTHORIZATION },
348 { 0, "X_LDERRNO", LDAP_API_FEATURE_X_LDERRNO },
349 { 0, "X_MEMCACHE", LDAP_API_FEATURE_X_MEMCACHE },
350 { 0, "X_IO_FUNCTIONS", LDAP_API_FEATURE_X_IO_FUNCTIONS },
351 { 0, "X_EXTIO_FUNCTIONS", LDAP_API_FEATURE_X_EXTIO_FUNCTIONS },
352 { 0, "X_DNS_FUNCTIONS", LDAP_API_FEATURE_X_DNS_FUNCTIONS },
353 { 0, "X_MEMALLOC_FUNCTIONS", LDAP_API_FEATURE_X_MEMALLOC_FUNCTIONS },
354 { 0, "X_THREAD_FUNCTIONS", LDAP_API_FEATURE_X_THREAD_FUNCTIONS },
355 { 0, "X_EXTHREAD_FUNCTIONS", LDAP_API_FEATURE_X_EXTHREAD_FUNCTIONS },
356 { 0, "X_GETLANGVALUES", LDAP_API_FEATURE_X_GETLANGVALUES },
357 { 0, "X_CLIENT_SIDE_SORT", LDAP_API_FEATURE_X_CLIENT_SIDE_SORT },
358 { 0, "X_URL_FUNCTIONS", LDAP_API_FEATURE_X_URL_FUNCTIONS },
359 { 0, "X_FILTER_FUNCTIONS", LDAP_API_FEATURE_X_FILTER_FUNCTIONS },
360 };
361
362 #define NSLDAPI_EXTENSIONS_COUNT \
363 (sizeof(nsldapi_extensions)/sizeof(LDAPAPIFeatureInfo))
364
365 /*
366 * Retrieve information about this implementation of the LDAP API.
367 * Returns an LDAP error code.
368 */
369 static int
nsldapi_get_api_info(LDAPAPIInfo * aip)370 nsldapi_get_api_info( LDAPAPIInfo *aip )
371 {
372 int i;
373
374 if ( aip == NULL ) {
375 return( LDAP_PARAM_ERROR );
376 }
377
378 aip->ldapai_api_version = LDAP_API_VERSION;
379
380 if ( aip->ldapai_info_version != LDAP_API_INFO_VERSION ) {
381 aip->ldapai_info_version = LDAP_API_INFO_VERSION;
382 return( LDAP_PARAM_ERROR );
383 }
384
385 aip->ldapai_protocol_version = LDAP_VERSION_MAX;
386 aip->ldapai_vendor_version = LDAP_VENDOR_VERSION;
387
388 if (( aip->ldapai_vendor_name = nsldapi_strdup( LDAP_VENDOR_NAME ))
389 == NULL ) {
390 return( LDAP_NO_MEMORY );
391 }
392
393 if ( NSLDAPI_EXTENSIONS_COUNT < 1 ) {
394 aip->ldapai_extensions = NULL;
395 } else {
396 if (( aip->ldapai_extensions = NSLDAPI_CALLOC(
397 NSLDAPI_EXTENSIONS_COUNT + 1, sizeof(char *))) == NULL ) {
398 NSLDAPI_FREE( aip->ldapai_vendor_name );
399 aip->ldapai_vendor_name = NULL;
400 return( LDAP_NO_MEMORY );
401 }
402
403 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) {
404 if (( aip->ldapai_extensions[i] = nsldapi_strdup(
405 nsldapi_extensions[i].ldapaif_name )) == NULL ) {
406 ldap_value_free( aip->ldapai_extensions );
407 NSLDAPI_FREE( aip->ldapai_vendor_name );
408 aip->ldapai_extensions = NULL;
409 aip->ldapai_vendor_name = NULL;
410 return( LDAP_NO_MEMORY );
411 }
412 }
413 }
414
415 return( LDAP_SUCCESS );
416 }
417
418
419 /*
420 * Retrieves information about a specific extended feature of the LDAP API/
421 * Returns an LDAP error code.
422 */
423 static int
nsldapi_get_feature_info(LDAPAPIFeatureInfo * fip)424 nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip )
425 {
426 int i;
427
428 if ( fip == NULL || fip->ldapaif_name == NULL ) {
429 return( LDAP_PARAM_ERROR );
430 }
431
432 if ( fip->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION ) {
433 fip->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
434 return( LDAP_PARAM_ERROR );
435 }
436
437 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) {
438 if ( strcmp( fip->ldapaif_name,
439 nsldapi_extensions[i].ldapaif_name ) == 0 ) {
440 fip->ldapaif_version =
441 nsldapi_extensions[i].ldapaif_version;
442 break;
443 }
444 }
445
446 return(( i < NSLDAPI_EXTENSIONS_COUNT ) ? LDAP_SUCCESS
447 : LDAP_PARAM_ERROR );
448 }
449