1 /* 2 * WLDAP32 - LDAP support for Wine 3 * 4 * Copyright 2005 Hans Leidekker 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "config.h" 22 #include "wine/port.h" 23 24 #include <stdarg.h> 25 #ifdef HAVE_LDAP_H 26 #include <ldap.h> 27 #endif 28 29 #include "windef.h" 30 #include "winbase.h" 31 #include "winnls.h" 32 33 #include "winldap_private.h" 34 #include "wldap32.h" 35 #include "wine/debug.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(wldap32); 38 39 /*********************************************************************** 40 * ldap_parse_extended_resultA (WLDAP32.@) 41 * 42 * See ldap_parse_extended_resultW. 43 */ 44 ULONG CDECL ldap_parse_extended_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 45 PCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free ) 46 { 47 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 48 #ifdef HAVE_LDAP 49 WCHAR *oidW = NULL; 50 51 TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free ); 52 53 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 54 if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; 55 56 ret = ldap_parse_extended_resultW( ld, result, &oidW, data, free ); 57 58 if (oid) { 59 *oid = strWtoA( oidW ); 60 if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY; 61 ldap_memfreeW( oidW ); 62 } 63 64 #endif 65 return ret; 66 } 67 68 /*********************************************************************** 69 * ldap_parse_extended_resultW (WLDAP32.@) 70 * 71 * Parse the result of an extended operation. 72 * 73 * PARAMS 74 * ld [I] Pointer to an LDAP context. 75 * result [I] Result message from an extended operation. 76 * oid [O] OID of the extended operation. 77 * data [O] Result data. 78 * free [I] Free the result message? 79 * 80 * RETURNS 81 * Success: LDAP_SUCCESS 82 * Failure: An LDAP error code. 83 * 84 * NOTES 85 * Free the OID and result data with ldap_memfree. Pass a nonzero 86 * value for 'free' or call ldap_msgfree to free the result message. 87 */ 88 ULONG CDECL ldap_parse_extended_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 89 PWCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free ) 90 { 91 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 92 #ifdef HAVE_LDAP 93 char *oidU = NULL; 94 95 TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free ); 96 97 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 98 if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; 99 100 ret = map_error( ldap_parse_extended_result( ld, result, &oidU, (struct berval **)data, free ) ); 101 102 if (oid) { 103 *oid = strUtoW( oidU ); 104 if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY; 105 ldap_memfree( oidU ); 106 } 107 108 #endif 109 return ret; 110 } 111 112 /*********************************************************************** 113 * ldap_parse_referenceA (WLDAP32.@) 114 * 115 * See ldap_parse_referenceW. 116 */ 117 ULONG CDECL ldap_parse_referenceA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message, 118 PCHAR **referrals ) 119 { 120 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 121 #ifdef HAVE_LDAP 122 WCHAR **referralsW = NULL; 123 124 TRACE( "(%p, %p, %p)\n", ld, message, referrals ); 125 126 if (!ld) return ~0u; 127 128 ret = ldap_parse_referenceW( ld, message, &referralsW ); 129 130 *referrals = strarrayWtoA( referralsW ); 131 ldap_value_freeW( referralsW ); 132 133 #endif 134 return ret; 135 } 136 137 /*********************************************************************** 138 * ldap_parse_referenceW (WLDAP32.@) 139 * 140 * Return any referrals from a result message. 141 * 142 * PARAMS 143 * ld [I] Pointer to an LDAP context. 144 * result [I] Result message. 145 * referrals [O] Array of referral URLs. 146 * 147 * RETURNS 148 * Success: LDAP_SUCCESS 149 * Failure: An LDAP error code. 150 * 151 * NOTES 152 * Free the referrals with ldap_value_free. 153 */ 154 ULONG CDECL ldap_parse_referenceW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message, 155 PWCHAR **referrals ) 156 { 157 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 158 #ifdef HAVE_LDAP_PARSE_REFERENCE 159 char **referralsU = NULL; 160 161 TRACE( "(%p, %p, %p)\n", ld, message, referrals ); 162 163 if (!ld) return ~0u; 164 165 ret = map_error( ldap_parse_reference( ld, message, &referralsU, NULL, 0 )); 166 167 *referrals = strarrayUtoW( referralsU ); 168 ldap_memfree( referralsU ); 169 170 #endif 171 return ret; 172 } 173 174 /*********************************************************************** 175 * ldap_parse_resultA (WLDAP32.@) 176 * 177 * See ldap_parse_resultW. 178 */ 179 ULONG CDECL ldap_parse_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 180 ULONG *retcode, PCHAR *matched, PCHAR *error, PCHAR **referrals, 181 PLDAPControlA **serverctrls, BOOLEAN free ) 182 { 183 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 184 #ifdef HAVE_LDAP 185 WCHAR *matchedW = NULL, *errorW = NULL, **referralsW = NULL; 186 LDAPControlW **serverctrlsW = NULL; 187 188 TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, 189 matched, error, referrals, serverctrls, free ); 190 191 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 192 193 ret = ldap_parse_resultW( ld, result, retcode, &matchedW, &errorW, 194 &referralsW, &serverctrlsW, free ); 195 196 if (matched) *matched = strWtoA( matchedW ); 197 if (error) *error = strWtoA( errorW ); 198 199 if (referrals) *referrals = strarrayWtoA( referralsW ); 200 if (serverctrls) *serverctrls = controlarrayWtoA( serverctrlsW ); 201 202 ldap_memfreeW( matchedW ); 203 ldap_memfreeW( errorW ); 204 ldap_value_freeW( referralsW ); 205 ldap_controls_freeW( serverctrlsW ); 206 207 #endif 208 return ret; 209 } 210 211 /*********************************************************************** 212 * ldap_parse_resultW (WLDAP32.@) 213 * 214 * Parse a result message. 215 * 216 * PARAMS 217 * ld [I] Pointer to an LDAP context. 218 * result [I] Result message. 219 * retcode [O] Return code for the server operation. 220 * matched [O] DNs matched in the operation. 221 * error [O] Error message for the operation. 222 * referrals [O] Referrals found in the result message. 223 * serverctrls [O] Controls used in the operation. 224 * free [I] Free the result message? 225 * 226 * RETURNS 227 * Success: LDAP_SUCCESS 228 * Failure: An LDAP error code. 229 * 230 * NOTES 231 * Free the DNs and error message with ldap_memfree. Free 232 * the referrals with ldap_value_free and the controls with 233 * ldap_controls_free. Pass a nonzero value for 'free' or call 234 * ldap_msgfree to free the result message. 235 */ 236 ULONG CDECL ldap_parse_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 237 ULONG *retcode, PWCHAR *matched, PWCHAR *error, PWCHAR **referrals, 238 PLDAPControlW **serverctrls, BOOLEAN free ) 239 { 240 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 241 #ifdef HAVE_LDAP 242 char *matchedU = NULL, *errorU = NULL, **referralsU = NULL; 243 LDAPControl **serverctrlsU = NULL; 244 245 TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, 246 matched, error, referrals, serverctrls, free ); 247 248 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 249 250 ret = map_error( ldap_parse_result( ld, result, (int *)retcode, &matchedU, &errorU, 251 &referralsU, &serverctrlsU, free )); 252 253 if (matched) *matched = strUtoW( matchedU ); 254 if (error) *error = strUtoW( errorU ); 255 256 if (referrals) *referrals = strarrayUtoW( referralsU ); 257 if (serverctrls) *serverctrls = controlarrayUtoW( serverctrlsU ); 258 259 ldap_memfree( matchedU ); 260 ldap_memfree( errorU ); 261 strarrayfreeU( referralsU ); 262 ldap_controls_free( serverctrlsU ); 263 264 #endif 265 return ret; 266 } 267 268 /*********************************************************************** 269 * ldap_parse_sort_controlA (WLDAP32.@) 270 * 271 * See ldap_parse_sort_controlW. 272 */ 273 ULONG CDECL ldap_parse_sort_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control, 274 ULONG *result, PCHAR *attr ) 275 { 276 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 277 #ifdef HAVE_LDAP 278 WCHAR *attrW = NULL; 279 LDAPControlW **controlW = NULL; 280 281 TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr ); 282 283 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 284 if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; 285 286 controlW = controlarrayAtoW( control ); 287 if (!controlW) return WLDAP32_LDAP_NO_MEMORY; 288 289 ret = ldap_parse_sort_controlW( ld, controlW, result, &attrW ); 290 291 *attr = strWtoA( attrW ); 292 controlarrayfreeW( controlW ); 293 294 #endif 295 return ret; 296 } 297 298 /*********************************************************************** 299 * ldap_parse_sort_controlW (WLDAP32.@) 300 * 301 * Parse a sort control. 302 * 303 * PARAMS 304 * ld [I] Pointer to an LDAP context. 305 * control [I] Control obtained from a result message. 306 * result [O] Result code. 307 * attr [O] Failing attribute. 308 * 309 * RETURNS 310 * Success: LDAP_SUCCESS 311 * Failure: An LDAP error code. 312 * 313 * NOTES 314 * If the function fails, free the failing attribute with ldap_memfree. 315 */ 316 ULONG CDECL ldap_parse_sort_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control, 317 ULONG *result, PWCHAR *attr ) 318 { 319 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 320 #ifdef HAVE_LDAP 321 char *attrU = NULL; 322 LDAPControl **controlU = NULL; 323 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL 324 unsigned long res; 325 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL) 326 ber_int_t res; 327 LDAPControl *sortcontrol = NULL; 328 unsigned int i; 329 #endif 330 331 TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr ); 332 333 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 334 if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; 335 336 controlU = controlarrayWtoU( control ); 337 if (!controlU) return WLDAP32_LDAP_NO_MEMORY; 338 339 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL 340 if (!(ret = ldap_parse_sort_control( ld, controlU, &res, &attrU ))) 341 { 342 *result = res; 343 *attr = strUtoW( attrU ); 344 } 345 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL) 346 for (i = 0; controlU[i]; i++) 347 { 348 if (!strcmp( LDAP_SERVER_RESP_SORT_OID, controlU[i]->ldctl_oid )) 349 sortcontrol = controlU[i]; 350 } 351 if (!sortcontrol) 352 { 353 controlarrayfreeU( controlU ); 354 return WLDAP32_LDAP_CONTROL_NOT_FOUND; 355 } 356 if (!(ret = ldap_parse_sortresponse_control( ld, sortcontrol, &res, &attrU ))) 357 { 358 *result = res; 359 *attr = strUtoW( attrU ); 360 } 361 #endif 362 controlarrayfreeU( controlU ); 363 364 #endif 365 return map_error( ret ); 366 } 367 368 /*********************************************************************** 369 * ldap_parse_vlv_controlA (WLDAP32.@) 370 * 371 * See ldap_parse_vlv_controlW. 372 */ 373 INT CDECL ldap_parse_vlv_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control, 374 PULONG targetpos, PULONG listcount, 375 struct WLDAP32_berval **context, PINT errcode ) 376 { 377 int ret = WLDAP32_LDAP_NOT_SUPPORTED; 378 #ifdef HAVE_LDAP 379 LDAPControlW **controlW = NULL; 380 381 TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos, 382 listcount, context, errcode ); 383 384 if (!ld) return ~0u; 385 386 if (control) { 387 controlW = controlarrayAtoW( control ); 388 if (!controlW) return WLDAP32_LDAP_NO_MEMORY; 389 } 390 391 ret = ldap_parse_vlv_controlW( ld, controlW, targetpos, listcount, 392 context, errcode ); 393 394 controlarrayfreeW( controlW ); 395 396 #endif 397 return ret; 398 } 399 400 /*********************************************************************** 401 * ldap_parse_vlv_controlW (WLDAP32.@) 402 * 403 * Parse a virtual list view control. 404 * 405 * PARAMS 406 * ld [I] Pointer to an LDAP context. 407 * control [I] Controls obtained from a result message. 408 * targetpos [O] Position of the target in the result list. 409 * listcount [O] Estimate of the number of results in the list. 410 * context [O] Server side context. 411 * errcode [O] Error code from the listview operation. 412 * 413 * RETURNS 414 * Success: LDAP_SUCCESS 415 * Failure: An LDAP error code. 416 * 417 * NOTES 418 * Free the server context with ber_bvfree. 419 */ 420 INT CDECL ldap_parse_vlv_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control, 421 PULONG targetpos, PULONG listcount, 422 struct WLDAP32_berval **context, PINT errcode ) 423 { 424 int ret = WLDAP32_LDAP_NOT_SUPPORTED; 425 #ifdef HAVE_LDAP 426 LDAPControl **controlU = NULL; 427 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL 428 unsigned long pos, count; 429 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL) 430 ber_int_t pos, count; 431 LDAPControl *vlvcontrol = NULL; 432 unsigned int i; 433 #endif 434 435 TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos, 436 listcount, context, errcode ); 437 438 if (!ld || !control) return ~0u; 439 440 controlU = controlarrayWtoU( control ); 441 if (!controlU) return WLDAP32_LDAP_NO_MEMORY; 442 443 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL 444 if (!(ret = ldap_parse_vlv_control( ld, controlU, &pos, &count, 445 (struct berval **)context, errcode ))) 446 { 447 *targetpos = pos; 448 *listcount = count; 449 } 450 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL) 451 for (i = 0; controlU[i]; i++) 452 { 453 if (!strcmp( LDAP_CONTROL_VLVRESPONSE, controlU[i]->ldctl_oid )) 454 vlvcontrol = controlU[i]; 455 } 456 if (!vlvcontrol) 457 { 458 controlarrayfreeU( controlU ); 459 return WLDAP32_LDAP_CONTROL_NOT_FOUND; 460 } 461 if (!(ret = ldap_parse_vlvresponse_control( ld, vlvcontrol, &pos, &count, 462 (struct berval **)context, errcode ))) 463 { 464 *targetpos = pos; 465 *listcount = count; 466 } 467 #endif 468 controlarrayfreeU( controlU ); 469 470 #endif 471 return map_error( ret ); 472 } 473