2 * WLDAP32 - LDAP support for Wine
4 * Copyright 2005 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "winldap_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
32 #ifndef LDAP_OPT_SERVER_CONTROLS
33 #define LDAP_OPT_SERVER_CONTROLS 0x0012
36 /***********************************************************************
37 * ldap_get_optionA (WLDAP32.@)
39 * See ldap_get_optionW.
41 ULONG CDECL
ldap_get_optionA( LDAP
*ld
, int option
, void *value
)
45 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
47 if (!ld
|| !value
) return LDAP_PARAM_ERROR
;
51 case LDAP_OPT_API_FEATURE_INFO
:
53 LDAPAPIFeatureInfoW featureW
;
54 LDAPAPIFeatureInfoA
*featureA
= value
;
56 if (!featureA
->ldapaif_name
) return LDAP_PARAM_ERROR
;
58 featureW
.ldapaif_info_version
= featureA
->ldapaif_info_version
;
59 if (!(featureW
.ldapaif_name
= strAtoW( featureA
->ldapaif_name
))) return LDAP_NO_MEMORY
;
60 featureW
.ldapaif_version
= 0;
62 ret
= ldap_get_optionW( ld
, option
, &featureW
);
64 if (ret
== LDAP_SUCCESS
) featureA
->ldapaif_version
= featureW
.ldapaif_version
;
65 free( featureW
.ldapaif_name
);
68 case LDAP_OPT_API_INFO
:
71 LDAPAPIInfoA
*infoA
= value
;
73 memset( &infoW
, 0, sizeof(infoW
) );
74 infoW
.ldapai_info_version
= infoA
->ldapai_info_version
;
76 ret
= ldap_get_optionW( ld
, option
, &infoW
);
77 if (ret
== LDAP_SUCCESS
)
79 infoA
->ldapai_api_version
= infoW
.ldapai_api_version
;
80 infoA
->ldapai_protocol_version
= infoW
.ldapai_protocol_version
;
82 if (infoW
.ldapai_extensions
&& !(infoA
->ldapai_extensions
= strarrayWtoA( infoW
.ldapai_extensions
)))
83 return LDAP_NO_MEMORY
;
84 if (infoW
.ldapai_vendor_name
&& !(infoA
->ldapai_vendor_name
= strWtoA( infoW
.ldapai_vendor_name
)))
86 ldap_value_freeW( infoW
.ldapai_extensions
);
87 return LDAP_NO_MEMORY
;
89 infoA
->ldapai_vendor_version
= infoW
.ldapai_vendor_version
;
91 ldap_value_freeW( infoW
.ldapai_extensions
);
92 ldap_memfreeW( infoW
.ldapai_vendor_name
);
99 case LDAP_OPT_ERROR_NUMBER
:
100 case LDAP_OPT_PROTOCOL_VERSION
:
101 case LDAP_OPT_REFERRALS
:
102 case LDAP_OPT_SIZELIMIT
:
103 case LDAP_OPT_TIMELIMIT
:
104 return ldap_get_optionW( ld
, option
, value
);
106 case LDAP_OPT_CACHE_ENABLE
:
107 case LDAP_OPT_CACHE_FN_PTRS
:
108 case LDAP_OPT_CACHE_STRATEGY
:
109 case LDAP_OPT_IO_FN_PTRS
:
110 case LDAP_OPT_REBIND_ARG
:
111 case LDAP_OPT_REBIND_FN
:
112 case LDAP_OPT_RESTART
:
113 case LDAP_OPT_THREAD_FN_PTRS
:
114 return LDAP_LOCAL_ERROR
;
116 case LDAP_OPT_AREC_EXCLUSIVE
:
117 case LDAP_OPT_AUTO_RECONNECT
:
118 case LDAP_OPT_CLIENT_CERTIFICATE
:
119 case LDAP_OPT_DNSDOMAIN_NAME
:
120 case LDAP_OPT_ENCRYPT
:
121 case LDAP_OPT_ERROR_STRING
:
122 case LDAP_OPT_FAST_CONCURRENT_BIND
:
123 case LDAP_OPT_GETDSNAME_FLAGS
:
124 case LDAP_OPT_HOST_NAME
:
125 case LDAP_OPT_HOST_REACHABLE
:
126 case LDAP_OPT_PING_KEEP_ALIVE
:
127 case LDAP_OPT_PING_LIMIT
:
128 case LDAP_OPT_PING_WAIT_TIME
:
129 case LDAP_OPT_PROMPT_CREDENTIALS
:
130 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
131 case LDAP_OPT_REFERRAL_CALLBACK
:
132 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
133 case LDAP_OPT_ROOTDSE_CACHE
:
134 case LDAP_OPT_SASL_METHOD
:
135 case LDAP_OPT_SECURITY_CONTEXT
:
136 case LDAP_OPT_SEND_TIMEOUT
:
137 case LDAP_OPT_SERVER_CERTIFICATE
:
138 case LDAP_OPT_SERVER_CONTROLS
:
139 case LDAP_OPT_SERVER_ERROR
:
140 case LDAP_OPT_SERVER_EXT_ERROR
:
143 case LDAP_OPT_SSL_INFO
:
144 case LDAP_OPT_SSPI_FLAGS
:
145 case LDAP_OPT_TCP_KEEPALIVE
:
146 FIXME( "Unsupported option: 0x%02x\n", option
);
147 return LDAP_NOT_SUPPORTED
;
150 FIXME( "Unknown option: 0x%02x\n", option
);
151 return LDAP_LOCAL_ERROR
;
155 /***********************************************************************
156 * ldap_get_optionW (WLDAP32.@)
158 * Retrieve option values for a given LDAP context.
161 * ld [I] Pointer to an LDAP context.
162 * option [I] Option to get values for.
163 * value [O] Pointer to option values.
166 * Success: LDAP_SUCCESS
167 * Failure: An LDAP error code.
169 ULONG CDECL
ldap_get_optionW( LDAP
*ld
, int option
, void *value
)
173 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
175 if (!ld
|| !value
) return LDAP_PARAM_ERROR
;
179 case LDAP_OPT_API_FEATURE_INFO
:
181 LDAPAPIFeatureInfoU featureU
;
182 LDAPAPIFeatureInfoW
*featureW
= value
;
184 if (!featureW
->ldapaif_name
) return LDAP_PARAM_ERROR
;
186 featureU
.ldapaif_info_version
= featureW
->ldapaif_info_version
;
187 if (!(featureU
.ldapaif_name
= strWtoU( featureW
->ldapaif_name
))) return LDAP_NO_MEMORY
;
188 featureU
.ldapaif_version
= 0;
190 ret
= map_error( ldap_funcs
->fn_ldap_get_option( CTX(ld
), option
, &featureU
) );
192 if (ret
== LDAP_SUCCESS
) featureW
->ldapaif_version
= featureU
.ldapaif_version
;
193 free( featureU
.ldapaif_name
);
196 case LDAP_OPT_API_INFO
:
199 LDAPAPIInfoW
*infoW
= value
;
201 memset( &infoU
, 0, sizeof(infoU
) );
202 infoU
.ldapai_info_version
= infoW
->ldapai_info_version
;
204 ret
= map_error( ldap_funcs
->fn_ldap_get_option( CTX(ld
), option
, &infoU
) );
205 if (ret
== LDAP_SUCCESS
)
207 infoW
->ldapai_api_version
= infoU
.ldapai_api_version
;
208 infoW
->ldapai_protocol_version
= infoU
.ldapai_protocol_version
;
210 if (infoU
.ldapai_extensions
&& !(infoW
->ldapai_extensions
= strarrayUtoW( infoU
.ldapai_extensions
)))
211 return LDAP_NO_MEMORY
;
212 if (infoU
.ldapai_vendor_name
&& !(infoW
->ldapai_vendor_name
= strUtoW( infoU
.ldapai_vendor_name
)))
214 ldap_funcs
->fn_ldap_memvfree( (void **)infoU
.ldapai_extensions
);
215 return LDAP_NO_MEMORY
;
217 infoW
->ldapai_vendor_version
= infoU
.ldapai_vendor_version
;
219 ldap_funcs
->fn_ldap_memvfree( (void **)infoU
.ldapai_extensions
);
220 ldap_funcs
->fn_ldap_memfree( infoU
.ldapai_vendor_name
);
227 case LDAP_OPT_ERROR_NUMBER
:
228 case LDAP_OPT_PROTOCOL_VERSION
:
229 case LDAP_OPT_REFERRALS
:
230 case LDAP_OPT_SIZELIMIT
:
231 case LDAP_OPT_TIMELIMIT
:
232 return map_error( ldap_funcs
->fn_ldap_get_option( CTX(ld
), option
, value
));
234 case LDAP_OPT_CACHE_ENABLE
:
235 case LDAP_OPT_CACHE_FN_PTRS
:
236 case LDAP_OPT_CACHE_STRATEGY
:
237 case LDAP_OPT_IO_FN_PTRS
:
238 case LDAP_OPT_REBIND_ARG
:
239 case LDAP_OPT_REBIND_FN
:
240 case LDAP_OPT_RESTART
:
241 case LDAP_OPT_THREAD_FN_PTRS
:
242 return LDAP_LOCAL_ERROR
;
244 case LDAP_OPT_AREC_EXCLUSIVE
:
245 case LDAP_OPT_AUTO_RECONNECT
:
246 case LDAP_OPT_CLIENT_CERTIFICATE
:
247 case LDAP_OPT_DNSDOMAIN_NAME
:
248 case LDAP_OPT_ENCRYPT
:
249 case LDAP_OPT_ERROR_STRING
:
250 case LDAP_OPT_FAST_CONCURRENT_BIND
:
251 case LDAP_OPT_GETDSNAME_FLAGS
:
252 case LDAP_OPT_HOST_NAME
:
253 case LDAP_OPT_HOST_REACHABLE
:
254 case LDAP_OPT_PING_KEEP_ALIVE
:
255 case LDAP_OPT_PING_LIMIT
:
256 case LDAP_OPT_PING_WAIT_TIME
:
257 case LDAP_OPT_PROMPT_CREDENTIALS
:
258 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
259 case LDAP_OPT_REFERRAL_CALLBACK
:
260 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
261 case LDAP_OPT_ROOTDSE_CACHE
:
262 case LDAP_OPT_SASL_METHOD
:
263 case LDAP_OPT_SECURITY_CONTEXT
:
264 case LDAP_OPT_SEND_TIMEOUT
:
265 case LDAP_OPT_SERVER_CERTIFICATE
:
266 case LDAP_OPT_SERVER_CONTROLS
:
267 case LDAP_OPT_SERVER_ERROR
:
268 case LDAP_OPT_SERVER_EXT_ERROR
:
271 case LDAP_OPT_SSL_INFO
:
272 case LDAP_OPT_SSPI_FLAGS
:
273 case LDAP_OPT_TCP_KEEPALIVE
:
274 FIXME( "Unsupported option: 0x%02x\n", option
);
275 return LDAP_NOT_SUPPORTED
;
278 FIXME( "Unknown option: 0x%02x\n", option
);
279 return LDAP_LOCAL_ERROR
;
283 /***********************************************************************
284 * ldap_set_optionA (WLDAP32.@)
286 * See ldap_set_optionW.
288 ULONG CDECL
ldap_set_optionA( LDAP
*ld
, int option
, void *value
)
292 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
294 if (!ld
) return LDAP_PARAM_ERROR
;
298 case LDAP_OPT_SERVER_CONTROLS
:
300 LDAPControlW
**ctrlsW
;
301 if (!(ctrlsW
= controlarrayAtoW( value
))) return LDAP_NO_MEMORY
;
302 ret
= ldap_set_optionW( ld
, option
, ctrlsW
);
303 controlarrayfreeW( ctrlsW
);
308 case LDAP_OPT_ERROR_NUMBER
:
309 case LDAP_OPT_PROTOCOL_VERSION
:
310 case LDAP_OPT_REFERRALS
:
311 case LDAP_OPT_SIZELIMIT
:
312 case LDAP_OPT_TIMELIMIT
:
313 return ldap_set_optionW( ld
, option
, value
);
315 case LDAP_OPT_CACHE_ENABLE
:
316 case LDAP_OPT_CACHE_FN_PTRS
:
317 case LDAP_OPT_CACHE_STRATEGY
:
318 case LDAP_OPT_IO_FN_PTRS
:
319 case LDAP_OPT_REBIND_ARG
:
320 case LDAP_OPT_REBIND_FN
:
321 case LDAP_OPT_RESTART
:
322 case LDAP_OPT_THREAD_FN_PTRS
:
323 return LDAP_LOCAL_ERROR
;
325 case LDAP_OPT_API_FEATURE_INFO
:
326 case LDAP_OPT_API_INFO
:
327 return LDAP_UNWILLING_TO_PERFORM
;
329 case LDAP_OPT_AREC_EXCLUSIVE
:
330 case LDAP_OPT_AUTO_RECONNECT
:
331 case LDAP_OPT_CLIENT_CERTIFICATE
:
332 case LDAP_OPT_DNSDOMAIN_NAME
:
333 case LDAP_OPT_ENCRYPT
:
334 case LDAP_OPT_ERROR_STRING
:
335 case LDAP_OPT_FAST_CONCURRENT_BIND
:
336 case LDAP_OPT_GETDSNAME_FLAGS
:
337 case LDAP_OPT_HOST_NAME
:
338 case LDAP_OPT_HOST_REACHABLE
:
339 case LDAP_OPT_PING_KEEP_ALIVE
:
340 case LDAP_OPT_PING_LIMIT
:
341 case LDAP_OPT_PING_WAIT_TIME
:
342 case LDAP_OPT_PROMPT_CREDENTIALS
:
343 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
344 case LDAP_OPT_REFERRAL_CALLBACK
:
345 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
346 case LDAP_OPT_ROOTDSE_CACHE
:
347 case LDAP_OPT_SASL_METHOD
:
348 case LDAP_OPT_SECURITY_CONTEXT
:
349 case LDAP_OPT_SEND_TIMEOUT
:
350 case LDAP_OPT_SERVER_CERTIFICATE
:
351 case LDAP_OPT_SERVER_ERROR
:
352 case LDAP_OPT_SERVER_EXT_ERROR
:
355 case LDAP_OPT_SSL_INFO
:
356 case LDAP_OPT_SSPI_FLAGS
:
357 case LDAP_OPT_TCP_KEEPALIVE
:
358 FIXME( "Unsupported option: 0x%02x\n", option
);
359 return LDAP_NOT_SUPPORTED
;
362 FIXME( "Unknown option: 0x%02x\n", option
);
363 return LDAP_LOCAL_ERROR
;
367 static BOOL
query_supported_server_ctrls( LDAP
*ld
)
369 char *attrs
[] = { (char *)"supportedControl", NULL
};
371 struct bervalU
**ctrls
= SERVER_CTRLS(ld
);
374 if (ctrls
) return TRUE
;
376 ret
= map_error( ldap_funcs
->fn_ldap_search_ext_s( CTX(ld
), (char *)"", LDAP_SCOPE_BASE
, (char *)"(objectClass=*)",
377 attrs
, FALSE
, NULL
, NULL
, NULL
, 0, &res
) );
378 if (ret
!= LDAP_SUCCESS
) return FALSE
;
380 entry
= ldap_funcs
->fn_ldap_first_entry( CTX(ld
), res
);
384 ctrls
= ldap_funcs
->fn_ldap_get_values_len( CTX(ld
), entry
, attrs
[0] );
385 count
= ldap_funcs
->fn_ldap_count_values_len( ctrls
);
386 for (i
= 0; i
< count
; i
++) TRACE("%u: %s\n", i
, debugstr_an( ctrls
[i
]->bv_val
, ctrls
[i
]->bv_len
));
387 *(struct bervalU
***)&SERVER_CTRLS(ld
) = ctrls
;
390 ldap_funcs
->fn_ldap_msgfree( res
);
391 return ctrls
!= NULL
;
394 static BOOL
is_supported_server_ctrls( LDAP
*ld
, LDAPControlU
**ctrls
)
396 ULONG user_count
, server_count
, i
, n
, supported
= 0;
398 if (!query_supported_server_ctrls( ld
))
399 return TRUE
; /* can't verify, let the server handle it on next query */
401 user_count
= controlarraylenU( ctrls
);
402 server_count
= ldap_funcs
->fn_ldap_count_values_len( SERVER_CTRLS(ld
) );
404 for (n
= 0; n
< user_count
; n
++)
406 TRACE("looking for %s\n", debugstr_a(ctrls
[n
]->ldctl_oid
));
408 for (i
= 0; i
< server_count
; i
++)
410 struct bervalU
**server_ctrls
= SERVER_CTRLS(ld
);
411 if (!strncmp( ctrls
[n
]->ldctl_oid
, server_ctrls
[i
]->bv_val
, server_ctrls
[i
]->bv_len
))
419 return supported
== user_count
;
422 /***********************************************************************
423 * ldap_set_optionW (WLDAP32.@)
425 * Set option values for a given LDAP context.
428 * ld [I] Pointer to an LDAP context.
429 * option [I] Option to set values for.
430 * value [I] Pointer to option values.
433 * Success: LDAP_SUCCESS
434 * Failure: An LDAP error code.
437 * Set value to LDAP_OPT_ON or LDAP_OPT_OFF for on/off options.
439 ULONG CDECL
ldap_set_optionW( LDAP
*ld
, int option
, void *value
)
443 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
445 if (!ld
) return LDAP_PARAM_ERROR
;
449 case LDAP_OPT_SERVER_CONTROLS
:
451 LDAPControlU
**ctrlsU
;
453 if (!(ctrlsU
= controlarrayWtoU( value
))) return LDAP_NO_MEMORY
;
455 if (!is_supported_server_ctrls( ld
, ctrlsU
))
456 ret
= LDAP_PARAM_ERROR
;
458 ret
= map_error( ldap_funcs
->fn_ldap_set_option( CTX(ld
), option
, ctrlsU
) );
459 controlarrayfreeU( ctrlsU
);
462 case LDAP_OPT_REFERRALS
:
464 void *openldap_referral
= LDAP_OPT_ON
;
465 if (value
== LDAP_OPT_OFF
)
466 openldap_referral
= LDAP_OPT_OFF
;
468 FIXME("upgrading referral value %p to LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value
);
469 return map_error( ldap_funcs
->fn_ldap_set_option( CTX(ld
), option
, openldap_referral
) );
473 case LDAP_OPT_ERROR_NUMBER
:
474 case LDAP_OPT_PROTOCOL_VERSION
:
475 case LDAP_OPT_SIZELIMIT
:
476 case LDAP_OPT_TIMELIMIT
:
477 return map_error( ldap_funcs
->fn_ldap_set_option( CTX(ld
), option
, value
));
479 case LDAP_OPT_CACHE_ENABLE
:
480 case LDAP_OPT_CACHE_FN_PTRS
:
481 case LDAP_OPT_CACHE_STRATEGY
:
482 case LDAP_OPT_IO_FN_PTRS
:
483 case LDAP_OPT_REBIND_ARG
:
484 case LDAP_OPT_REBIND_FN
:
485 case LDAP_OPT_RESTART
:
486 case LDAP_OPT_THREAD_FN_PTRS
:
487 return LDAP_LOCAL_ERROR
;
489 case LDAP_OPT_API_FEATURE_INFO
:
490 case LDAP_OPT_API_INFO
:
491 return LDAP_UNWILLING_TO_PERFORM
;
493 case LDAP_OPT_AREC_EXCLUSIVE
:
494 case LDAP_OPT_AUTO_RECONNECT
:
495 case LDAP_OPT_CLIENT_CERTIFICATE
:
496 case LDAP_OPT_DNSDOMAIN_NAME
:
497 case LDAP_OPT_ENCRYPT
:
498 case LDAP_OPT_ERROR_STRING
:
499 case LDAP_OPT_FAST_CONCURRENT_BIND
:
500 case LDAP_OPT_GETDSNAME_FLAGS
:
501 case LDAP_OPT_HOST_NAME
:
502 case LDAP_OPT_HOST_REACHABLE
:
503 case LDAP_OPT_PING_KEEP_ALIVE
:
504 case LDAP_OPT_PING_LIMIT
:
505 case LDAP_OPT_PING_WAIT_TIME
:
506 case LDAP_OPT_PROMPT_CREDENTIALS
:
507 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
508 case LDAP_OPT_REFERRAL_CALLBACK
:
509 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
510 case LDAP_OPT_ROOTDSE_CACHE
:
511 case LDAP_OPT_SASL_METHOD
:
512 case LDAP_OPT_SECURITY_CONTEXT
:
513 case LDAP_OPT_SEND_TIMEOUT
:
514 case LDAP_OPT_SERVER_CERTIFICATE
:
515 case LDAP_OPT_SERVER_ERROR
:
516 case LDAP_OPT_SERVER_EXT_ERROR
:
519 case LDAP_OPT_SSL_INFO
:
520 case LDAP_OPT_SSPI_FLAGS
:
521 case LDAP_OPT_TCP_KEEPALIVE
:
522 FIXME( "Unsupported option: 0x%02x\n", option
);
523 return LDAP_NOT_SUPPORTED
;
526 FIXME( "Unknown option: 0x%02x\n", option
);
527 return LDAP_LOCAL_ERROR
;