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
22 #include "wine/port.h"
28 #ifdef HAVE_SASL_SASL_H
29 #include <sasl/sasl.h>
37 #include "winldap_private.h"
39 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
45 /***********************************************************************
46 * ldap_bindA (WLDAP32.@)
50 ULONG CDECL
ldap_bindA( WLDAP32_LDAP
*ld
, PCHAR dn
, PCHAR cred
, ULONG method
)
52 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
54 WCHAR
*dnW
= NULL
, *credW
= NULL
;
56 ret
= WLDAP32_LDAP_NO_MEMORY
;
58 TRACE( "(%p, %s, %p, 0x%08x)\n", ld
, debugstr_a(dn
), cred
, method
);
67 credW
= strAtoW( cred
);
68 if (!credW
) goto exit
;
71 ret
= ldap_bindW( ld
, dnW
, credW
, method
);
81 /***********************************************************************
82 * ldap_bindW (WLDAP32.@)
84 * Authenticate with an LDAP server (asynchronous operation).
87 * ld [I] Pointer to an LDAP context.
88 * dn [I] DN of entry to bind as.
89 * cred [I] Credentials (e.g. password string).
90 * method [I] Authentication method.
93 * Success: Message ID of the bind operation.
94 * Failure: An LDAP error code.
97 * Only LDAP_AUTH_SIMPLE is supported (just like native).
99 ULONG CDECL
ldap_bindW( WLDAP32_LDAP
*ld
, PWCHAR dn
, PWCHAR cred
, ULONG method
)
101 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
103 char *dnU
= NULL
, *credU
= NULL
;
104 struct berval pwd
= { 0, NULL
};
107 ret
= WLDAP32_LDAP_NO_MEMORY
;
109 TRACE( "(%p, %s, %p, 0x%08x)\n", ld
, debugstr_w(dn
), cred
, method
);
112 if (method
!= LDAP_AUTH_SIMPLE
) return WLDAP32_LDAP_PARAM_ERROR
;
119 credU
= strWtoU( cred
);
120 if (!credU
) goto exit
;
122 pwd
.bv_len
= strlen( credU
);
126 ret
= ldap_sasl_bind( ld
->ld
, dnU
, LDAP_SASL_SIMPLE
, &pwd
, NULL
, NULL
, &msg
);
128 if (ret
== LDAP_SUCCESS
)
141 /***********************************************************************
142 * ldap_bind_sA (WLDAP32.@)
146 ULONG CDECL
ldap_bind_sA( WLDAP32_LDAP
*ld
, PCHAR dn
, PCHAR cred
, ULONG method
)
148 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
150 WCHAR
*dnW
= NULL
, *credW
= NULL
;
152 ret
= WLDAP32_LDAP_NO_MEMORY
;
154 TRACE( "(%p, %s, %p, 0x%08x)\n", ld
, debugstr_a(dn
), cred
, method
);
156 if (!ld
) return WLDAP32_LDAP_PARAM_ERROR
;
163 if (method
== LDAP_AUTH_SIMPLE
)
165 credW
= strAtoW( cred
);
166 if (!credW
) goto exit
;
169 credW
= (WCHAR
*)cred
/* SEC_WINNT_AUTH_IDENTITY_A */;
172 ret
= ldap_bind_sW( ld
, dnW
, credW
, method
);
176 if (credW
!= (WCHAR
*)cred
) strfreeW( credW
);
184 static int sasl_interact( LDAP
*ld
, unsigned flags
, void *defaults
, void *interact
)
186 #ifdef HAVE_SASL_SASL_H
187 SEC_WINNT_AUTH_IDENTITY_A
*id
= defaults
;
188 sasl_interact_t
*sasl
= interact
;
190 TRACE( "%p,%08x,%p,%p\n", ld
, flags
, defaults
, interact
);
192 while (sasl
->id
!= SASL_CB_LIST_END
)
194 TRACE("sasl->id = %04lx\n", sasl
->id
);
196 if (sasl
->id
== SASL_CB_GETREALM
)
198 sasl
->result
= id
->Domain
;
199 sasl
->len
= id
->DomainLength
;
201 else if (sasl
->id
== SASL_CB_USER
)
203 sasl
->result
= id
->User
;
204 sasl
->len
= id
->UserLength
;
206 else if (sasl
->id
== SASL_CB_PASS
)
208 sasl
->result
= id
->Password
;
209 sasl
->len
= id
->PasswordLength
;
217 FIXME( "%p,%08x,%p,%p: stub\n", ld
, flags
, defaults
, interact
);
219 #endif /* HAVE_SASL_SASL_H */
222 #endif /* HAVE_LDAP */
224 /***********************************************************************
225 * ldap_bind_sW (WLDAP32.@)
227 * Authenticate with an LDAP server (synchronous operation).
230 * ld [I] Pointer to an LDAP context.
231 * dn [I] DN of entry to bind as.
232 * cred [I] Credentials (e.g. password string).
233 * method [I] Authentication method.
236 * Success: LDAP_SUCCESS
237 * Failure: An LDAP error code.
239 ULONG CDECL
ldap_bind_sW( WLDAP32_LDAP
*ld
, PWCHAR dn
, PWCHAR cred
, ULONG method
)
241 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
243 char *dnU
= NULL
, *credU
= NULL
;
244 struct berval pwd
= { 0, NULL
};
246 ret
= WLDAP32_LDAP_NO_MEMORY
;
248 TRACE( "(%p, %s, %p, 0x%08x)\n", ld
, debugstr_w(dn
), cred
, method
);
250 if (!ld
) return WLDAP32_LDAP_PARAM_ERROR
;
252 if (method
== LDAP_AUTH_SIMPLE
)
261 credU
= strWtoU( cred
);
262 if (!credU
) goto exit
;
264 pwd
.bv_len
= strlen( credU
);
268 ret
= map_error( ldap_sasl_bind_s( ld
->ld
, dnU
, LDAP_SASL_SIMPLE
, &pwd
, NULL
, NULL
, NULL
));
270 else if (method
== WLDAP32_LDAP_AUTH_NEGOTIATE
)
272 SEC_WINNT_AUTH_IDENTITY_A idU
;
273 SEC_WINNT_AUTH_IDENTITY_W idW
;
274 SEC_WINNT_AUTH_IDENTITY_W
*id
= (SEC_WINNT_AUTH_IDENTITY_W
*)cred
;
276 memset( &idU
, 0, sizeof(idU
) );
280 if (id
->Flags
& SEC_WINNT_AUTH_IDENTITY_ANSI
)
282 idW
.Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
283 idW
.Domain
= (unsigned short *)strnAtoW( (char *)id
->Domain
, id
->DomainLength
, &idW
.DomainLength
);
284 idW
.User
= (unsigned short *)strnAtoW( (char *)id
->User
, id
->UserLength
, &idW
.UserLength
);
285 idW
.Password
= (unsigned short *)strnAtoW( (char *)id
->Password
, id
->PasswordLength
, &idW
.PasswordLength
);
290 idU
.Domain
= (unsigned char *)strnWtoU( id
->Domain
, id
->DomainLength
, &idU
.DomainLength
);
291 idU
.User
= (unsigned char *)strnWtoU( id
->User
, id
->UserLength
, &idU
.UserLength
);
292 idU
.Password
= (unsigned char *)strnWtoU( id
->Password
, id
->PasswordLength
, &idU
.PasswordLength
);
295 ret
= map_error( ldap_sasl_interactive_bind_s( ld
->ld
,
296 NULL
/* server will ignore DN anyway */,
297 NULL
/* query supportedSASLMechanisms */,
298 NULL
, NULL
, LDAP_SASL_QUIET
, sasl_interact
, &idU
));
300 if (id
&& (id
->Flags
& SEC_WINNT_AUTH_IDENTITY_ANSI
))
302 strfreeW( (WCHAR
*)idW
.Domain
);
303 strfreeW( (WCHAR
*)idW
.User
);
304 strfreeW( (WCHAR
*)idW
.Password
);
307 strfreeU( (char *)idU
.Domain
);
308 strfreeU( (char *)idU
.User
);
309 strfreeU( (char *)idU
.Password
);
313 FIXME( "method %#x not supported\n", method
);
314 return WLDAP32_LDAP_PARAM_ERROR
;
325 /***********************************************************************
326 * ldap_sasl_bindA (WLDAP32.@)
328 * See ldap_sasl_bindW.
330 ULONG CDECL
ldap_sasl_bindA( WLDAP32_LDAP
*ld
, const PCHAR dn
,
331 const PCHAR mechanism
, const BERVAL
*cred
, PLDAPControlA
*serverctrls
,
332 PLDAPControlA
*clientctrls
, int *message
)
334 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
336 WCHAR
*dnW
, *mechanismW
= NULL
;
337 LDAPControlW
**serverctrlsW
= NULL
, **clientctrlsW
= NULL
;
339 ret
= WLDAP32_LDAP_NO_MEMORY
;
341 TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld
, debugstr_a(dn
),
342 debugstr_a(mechanism
), cred
, serverctrls
, clientctrls
, message
);
344 if (!ld
|| !dn
|| !mechanism
|| !cred
|| !message
)
345 return WLDAP32_LDAP_PARAM_ERROR
;
350 mechanismW
= strAtoW( mechanism
);
351 if (!mechanismW
) goto exit
;
354 serverctrlsW
= controlarrayAtoW( serverctrls
);
355 if (!serverctrlsW
) goto exit
;
358 clientctrlsW
= controlarrayAtoW( clientctrls
);
359 if (!clientctrlsW
) goto exit
;
362 ret
= ldap_sasl_bindW( ld
, dnW
, mechanismW
, cred
, serverctrlsW
, clientctrlsW
, message
);
366 strfreeW( mechanismW
);
367 controlarrayfreeW( serverctrlsW
);
368 controlarrayfreeW( clientctrlsW
);
374 /***********************************************************************
375 * ldap_sasl_bindW (WLDAP32.@)
377 * Authenticate with an LDAP server using SASL (asynchronous operation).
380 * ld [I] Pointer to an LDAP context.
381 * dn [I] DN of entry to bind as.
382 * mechanism [I] Authentication method.
383 * cred [I] Credentials.
384 * serverctrls [I] Array of LDAP server controls.
385 * clientctrls [I] Array of LDAP client controls.
386 * message [O] Message ID of the bind operation.
389 * Success: LDAP_SUCCESS
390 * Failure: An LDAP error code.
393 * The serverctrls and clientctrls parameters are optional and should
394 * be set to NULL if not used.
396 ULONG CDECL
ldap_sasl_bindW( WLDAP32_LDAP
*ld
, const PWCHAR dn
,
397 const PWCHAR mechanism
, const BERVAL
*cred
, PLDAPControlW
*serverctrls
,
398 PLDAPControlW
*clientctrls
, int *message
)
400 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
402 char *dnU
, *mechanismU
= NULL
;
403 LDAPControl
**serverctrlsU
= NULL
, **clientctrlsU
= NULL
;
406 ret
= WLDAP32_LDAP_NO_MEMORY
;
408 TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld
, debugstr_w(dn
),
409 debugstr_w(mechanism
), cred
, serverctrls
, clientctrls
, message
);
411 if (!ld
|| !dn
|| !mechanism
|| !cred
|| !message
)
412 return WLDAP32_LDAP_PARAM_ERROR
;
417 mechanismU
= strWtoU( mechanism
);
418 if (!mechanismU
) goto exit
;
421 serverctrlsU
= controlarrayWtoU( serverctrls
);
422 if (!serverctrlsU
) goto exit
;
425 clientctrlsU
= controlarrayWtoU( clientctrls
);
426 if (!clientctrlsU
) goto exit
;
429 credU
.bv_len
= cred
->bv_len
;
430 credU
.bv_val
= cred
->bv_val
;
432 ret
= map_error( ldap_sasl_bind( ld
->ld
, dnU
, mechanismU
, &credU
,
433 serverctrlsU
, clientctrlsU
, message
));
437 strfreeU( mechanismU
);
438 controlarrayfreeU( serverctrlsU
);
439 controlarrayfreeU( clientctrlsU
);
445 /***********************************************************************
446 * ldap_sasl_bind_sA (WLDAP32.@)
448 * See ldap_sasl_bind_sW.
450 ULONG CDECL
ldap_sasl_bind_sA( WLDAP32_LDAP
*ld
, const PCHAR dn
,
451 const PCHAR mechanism
, const BERVAL
*cred
, PLDAPControlA
*serverctrls
,
452 PLDAPControlA
*clientctrls
, PBERVAL
*serverdata
)
454 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
456 WCHAR
*dnW
, *mechanismW
= NULL
;
457 LDAPControlW
**serverctrlsW
= NULL
, **clientctrlsW
= NULL
;
459 ret
= WLDAP32_LDAP_NO_MEMORY
;
461 TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld
, debugstr_a(dn
),
462 debugstr_a(mechanism
), cred
, serverctrls
, clientctrls
, serverdata
);
464 if (!ld
|| !dn
|| !mechanism
|| !cred
|| !serverdata
)
465 return WLDAP32_LDAP_PARAM_ERROR
;
470 mechanismW
= strAtoW( mechanism
);
471 if (!mechanismW
) goto exit
;
474 serverctrlsW
= controlarrayAtoW( serverctrls
);
475 if (!serverctrlsW
) goto exit
;
478 clientctrlsW
= controlarrayAtoW( clientctrls
);
479 if (!clientctrlsW
) goto exit
;
482 ret
= ldap_sasl_bind_sW( ld
, dnW
, mechanismW
, cred
, serverctrlsW
, clientctrlsW
, serverdata
);
486 strfreeW( mechanismW
);
487 controlarrayfreeW( serverctrlsW
);
488 controlarrayfreeW( clientctrlsW
);
494 /***********************************************************************
495 * ldap_sasl_bind_sW (WLDAP32.@)
497 * Authenticate with an LDAP server using SASL (synchronous operation).
500 * ld [I] Pointer to an LDAP context.
501 * dn [I] DN of entry to bind as.
502 * mechanism [I] Authentication method.
503 * cred [I] Credentials.
504 * serverctrls [I] Array of LDAP server controls.
505 * clientctrls [I] Array of LDAP client controls.
506 * serverdata [O] Authentication response from the server.
509 * Success: LDAP_SUCCESS
510 * Failure: An LDAP error code.
513 * The serverctrls and clientctrls parameters are optional and should
514 * be set to NULL if not used.
516 ULONG CDECL
ldap_sasl_bind_sW( WLDAP32_LDAP
*ld
, const PWCHAR dn
,
517 const PWCHAR mechanism
, const BERVAL
*cred
, PLDAPControlW
*serverctrls
,
518 PLDAPControlW
*clientctrls
, PBERVAL
*serverdata
)
520 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
522 char *dnU
, *mechanismU
= NULL
;
523 LDAPControl
**serverctrlsU
= NULL
, **clientctrlsU
= NULL
;
526 ret
= WLDAP32_LDAP_NO_MEMORY
;
528 TRACE( "(%p, %s, %s, %p, %p, %p, %p)\n", ld
, debugstr_w(dn
),
529 debugstr_w(mechanism
), cred
, serverctrls
, clientctrls
, serverdata
);
531 if (!ld
|| !dn
|| !mechanism
|| !cred
|| !serverdata
)
532 return WLDAP32_LDAP_PARAM_ERROR
;
537 mechanismU
= strWtoU( mechanism
);
538 if (!mechanismU
) goto exit
;
541 serverctrlsU
= controlarrayWtoU( serverctrls
);
542 if (!serverctrlsU
) goto exit
;
545 clientctrlsU
= controlarrayWtoU( clientctrls
);
546 if (!clientctrlsU
) goto exit
;
549 credU
.bv_len
= cred
->bv_len
;
550 credU
.bv_val
= cred
->bv_val
;
552 ret
= map_error( ldap_sasl_bind_s( ld
->ld
, dnU
, mechanismU
, &credU
,
553 serverctrlsU
, clientctrlsU
, (struct berval
**)serverdata
));
557 strfreeU( mechanismU
);
558 controlarrayfreeU( serverctrlsU
);
559 controlarrayfreeU( clientctrlsU
);
565 /***********************************************************************
566 * ldap_simple_bindA (WLDAP32.@)
568 * See ldap_simple_bindW.
570 ULONG CDECL
ldap_simple_bindA( WLDAP32_LDAP
*ld
, PCHAR dn
, PCHAR passwd
)
572 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
574 WCHAR
*dnW
= NULL
, *passwdW
= NULL
;
576 ret
= WLDAP32_LDAP_NO_MEMORY
;
578 TRACE( "(%p, %s, %p)\n", ld
, debugstr_a(dn
), passwd
);
587 passwdW
= strAtoW( passwd
);
588 if (!passwdW
) goto exit
;
591 ret
= ldap_simple_bindW( ld
, dnW
, passwdW
);
601 /***********************************************************************
602 * ldap_simple_bindW (WLDAP32.@)
604 * Authenticate with an LDAP server (asynchronous operation).
607 * ld [I] Pointer to an LDAP context.
608 * dn [I] DN of entry to bind as.
609 * passwd [I] Password string.
612 * Success: Message ID of the bind operation.
613 * Failure: An LDAP error code.
616 * Set dn and passwd to NULL to bind as an anonymous user.
618 ULONG CDECL
ldap_simple_bindW( WLDAP32_LDAP
*ld
, PWCHAR dn
, PWCHAR passwd
)
620 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
622 char *dnU
= NULL
, *passwdU
= NULL
;
623 struct berval pwd
= { 0, NULL
};
626 ret
= WLDAP32_LDAP_NO_MEMORY
;
628 TRACE( "(%p, %s, %p)\n", ld
, debugstr_w(dn
), passwd
);
637 passwdU
= strWtoU( passwd
);
638 if (!passwdU
) goto exit
;
640 pwd
.bv_len
= strlen( passwdU
);
641 pwd
.bv_val
= passwdU
;
644 ret
= ldap_sasl_bind( ld
->ld
, dnU
, LDAP_SASL_SIMPLE
, &pwd
, NULL
, NULL
, &msg
);
646 if (ret
== LDAP_SUCCESS
)
659 /***********************************************************************
660 * ldap_simple_bind_sA (WLDAP32.@)
662 * See ldap_simple_bind_sW.
664 ULONG CDECL
ldap_simple_bind_sA( WLDAP32_LDAP
*ld
, PCHAR dn
, PCHAR passwd
)
666 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
668 WCHAR
*dnW
= NULL
, *passwdW
= NULL
;
670 ret
= WLDAP32_LDAP_NO_MEMORY
;
672 TRACE( "(%p, %s, %p)\n", ld
, debugstr_a(dn
), passwd
);
674 if (!ld
) return WLDAP32_LDAP_PARAM_ERROR
;
681 passwdW
= strAtoW( passwd
);
682 if (!passwdW
) goto exit
;
685 ret
= ldap_simple_bind_sW( ld
, dnW
, passwdW
);
695 /***********************************************************************
696 * ldap_simple_bind_sW (WLDAP32.@)
698 * Authenticate with an LDAP server (synchronous operation).
701 * ld [I] Pointer to an LDAP context.
702 * dn [I] DN of entry to bind as.
703 * passwd [I] Password string.
706 * Success: LDAP_SUCCESS
707 * Failure: An LDAP error code.
710 * Set dn and passwd to NULL to bind as an anonymous user.
712 ULONG CDECL
ldap_simple_bind_sW( WLDAP32_LDAP
*ld
, PWCHAR dn
, PWCHAR passwd
)
714 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
716 char *dnU
= NULL
, *passwdU
= NULL
;
717 struct berval pwd
= { 0, NULL
};
719 ret
= WLDAP32_LDAP_NO_MEMORY
;
721 TRACE( "(%p, %s, %p)\n", ld
, debugstr_w(dn
), passwd
);
723 if (!ld
) return WLDAP32_LDAP_PARAM_ERROR
;
730 passwdU
= strWtoU( passwd
);
731 if (!passwdU
) goto exit
;
733 pwd
.bv_len
= strlen( passwdU
);
734 pwd
.bv_val
= passwdU
;
737 ret
= map_error( ldap_sasl_bind_s( ld
->ld
, dnU
, LDAP_SASL_SIMPLE
, &pwd
, NULL
, NULL
, NULL
));
747 /***********************************************************************
748 * ldap_unbind (WLDAP32.@)
750 * Close LDAP connection and free resources (asynchronous operation).
753 * ld [I] Pointer to an LDAP context.
756 * Success: LDAP_SUCCESS
757 * Failure: An LDAP error code.
759 ULONG CDECL
WLDAP32_ldap_unbind( WLDAP32_LDAP
*ld
)
761 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
764 TRACE( "(%p)\n", ld
);
768 ret
= map_error( ldap_unbind_ext( ld
->ld
, NULL
, NULL
));
769 if ( ld
->ld_server_ctrls
)
770 ldap_value_free_len( ld
->ld_server_ctrls
);
774 ret
= WLDAP32_LDAP_PARAM_ERROR
;
780 /***********************************************************************
781 * ldap_unbind_s (WLDAP32.@)
783 * Close LDAP connection and free resources (synchronous operation).
786 * ld [I] Pointer to an LDAP context.
789 * Success: LDAP_SUCCESS
790 * Failure: An LDAP error code.
792 ULONG CDECL
WLDAP32_ldap_unbind_s( WLDAP32_LDAP
*ld
)
794 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
797 TRACE( "(%p)\n", ld
);
801 ret
= map_error( ldap_unbind_ext_s( ld
->ld
, NULL
, NULL
));
802 if ( ld
->ld_server_ctrls
)
803 ldap_value_free_len( ld
->ld_server_ctrls
);
807 ret
= WLDAP32_LDAP_PARAM_ERROR
;