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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/port.h"
24 #include "wine/debug.h"
36 #define LDAP_SUCCESS 0x00
37 #define LDAP_NOT_SUPPORTED 0x5c
40 #include "winldap_private.h"
44 /* Should eventually be determined by the algorithm documented on MSDN. */
45 static const WCHAR defaulthost
[] = { 'l','o','c','a','l','h','o','s','t',0 };
47 /* Split a space separated string of hostnames into a string array */
48 static char **split_hostnames( const char *hostnames
)
50 char **res
, *str
, *p
, *q
;
53 str
= strdupU( hostnames
);
54 if (!str
) return NULL
;
57 while (isspace( *p
)) p
++;
64 while (isspace( *p
)) p
++;
70 res
= HeapAlloc( GetProcessHeap(), 0, (i
+ 1) * sizeof(char *) );
73 HeapFree( GetProcessHeap(), 0, str
);
78 while (isspace( *p
)) p
++;
90 res
[i
] = strdupU( q
);
91 if (!res
[i
]) goto oom
;
94 while (isspace( *p
)) p
++;
100 res
[i
] = strdupU( q
);
101 if (!res
[i
]) goto oom
;
108 HeapFree( GetProcessHeap(), 0, str
);
112 for (--i
; i
>= 0; i
--)
115 HeapFree( GetProcessHeap(), 0, res
);
116 HeapFree( GetProcessHeap(), 0, str
);
121 /* Determine if a URL starts with a known LDAP scheme */
122 static int has_ldap_scheme( char *url
)
124 if (!strncasecmp( url
, "ldap://", 7 ) ||
125 !strncasecmp( url
, "ldaps://", 8 ) ||
126 !strncasecmp( url
, "ldapi://", 8 ) ||
127 !strncasecmp( url
, "cldap://", 8 )) return 1;
131 /* Flatten an array of hostnames into a space separated string of URLs.
132 * Prepend a given scheme and append a given portnumber to each hostname
135 static char *join_hostnames( char *scheme
, char **hostnames
, ULONG portnumber
)
137 char *res
, *p
, *q
, **v
;
138 unsigned int i
= 0, size
= 0;
139 static const char sep
[] = " ", fmt
[] = ":%ld";
142 sprintf( port
, fmt
, portnumber
);
144 for (v
= hostnames
; *v
; v
++)
146 if (!has_ldap_scheme( *v
))
148 size
+= strlen( scheme
);
152 /* skip past colon in scheme prefix */
153 q
= strchr( *v
, '/' );
155 size
+= strlen( *v
);
157 if (!strchr( q
, ':' ))
158 size
+= strlen( port
);
163 size
+= (i
- 1) * strlen( sep
);
165 res
= HeapAlloc( GetProcessHeap(), 0, size
+ 1 );
166 if (!res
) return NULL
;
169 for (v
= hostnames
; *v
; v
++)
177 if (!has_ldap_scheme( *v
))
180 p
+= strlen( scheme
);
184 /* skip past colon in scheme prefix */
185 q
= strchr( *v
, '/' );
190 if (!strchr( q
, ':' ))
199 static char *urlify_hostnames( char *scheme
, char *hostnames
, ULONG port
)
201 char *url
, **strarray
;
203 strarray
= split_hostnames( hostnames
);
204 url
= join_hostnames( scheme
, strarray
, port
);
205 strarrayfreeU( strarray
);
211 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
213 WLDAP32_LDAP
*cldap_openA( PCHAR hostname
, ULONG portnumber
)
216 WLDAP32_LDAP
*ld
= NULL
;
217 WCHAR
*hostnameW
= NULL
;
219 TRACE( "(%s, %ld)\n", debugstr_a(hostname
), portnumber
);
222 hostnameW
= strAtoW( hostname
);
223 if (!hostnameW
) goto exit
;
226 ld
= cldap_openW( hostnameW
, portnumber
);
229 strfreeW( hostnameW
);
236 WLDAP32_LDAP
*cldap_openW( PWCHAR hostname
, ULONG portnumber
)
240 char *hostnameU
= NULL
, *url
= NULL
;
242 TRACE( "(%s, %ld)\n", debugstr_w(hostname
), portnumber
);
245 hostnameU
= strWtoU( hostname
);
246 if (!hostnameU
) goto exit
;
249 hostnameU
= strWtoU( defaulthost
);
250 if (!hostnameU
) goto exit
;
253 url
= urlify_hostnames( "cldap://", hostnameU
, portnumber
);
256 ldap_initialize( &ld
, url
);
259 strfreeU( hostnameU
);
267 ULONG
ldap_connect( WLDAP32_LDAP
*ld
, LDAP_TIMEVAL
*timeout
)
269 TRACE( "(%p, %p)\n", ld
, timeout
);
271 if (!ld
|| !timeout
) return WLDAP32_LDAP_PARAM_ERROR
;
272 return LDAP_SUCCESS
; /* FIXME: do something, e.g. ping the host */
275 WLDAP32_LDAP
*ldap_initA( PCHAR hostname
, ULONG portnumber
)
278 WLDAP32_LDAP
*ld
= NULL
;
279 WCHAR
*hostnameW
= NULL
;
281 TRACE( "(%s, %ld)\n", debugstr_a(hostname
), portnumber
);
284 hostnameW
= strAtoW( hostname
);
285 if (!hostnameW
) goto exit
;
288 ld
= ldap_initW( hostnameW
, portnumber
);
291 strfreeW( hostnameW
);
298 WLDAP32_LDAP
*ldap_initW( PWCHAR hostname
, ULONG portnumber
)
302 char *hostnameU
= NULL
, *url
= NULL
;
304 TRACE( "(%s, %ld)\n", debugstr_w(hostname
), portnumber
);
307 hostnameU
= strWtoU( hostname
);
308 if (!hostnameU
) goto exit
;
311 hostnameU
= strWtoU( defaulthost
);
312 if (!hostnameU
) goto exit
;
315 url
= urlify_hostnames( "ldap://", hostnameU
, portnumber
);
318 ldap_initialize( &ld
, url
);
321 strfreeU( hostnameU
);
329 WLDAP32_LDAP
*ldap_openA( PCHAR hostname
, ULONG portnumber
)
332 WLDAP32_LDAP
*ld
= NULL
;
333 WCHAR
*hostnameW
= NULL
;
335 TRACE( "(%s, %ld)\n", debugstr_a(hostname
), portnumber
);
338 hostnameW
= strAtoW( hostname
);
339 if (!hostnameW
) goto exit
;
342 ld
= ldap_openW( hostnameW
, portnumber
);
345 strfreeW( hostnameW
);
352 WLDAP32_LDAP
*ldap_openW( PWCHAR hostname
, ULONG portnumber
)
356 char *hostnameU
= NULL
, *url
= NULL
;
358 TRACE( "(%s, %ld)\n", debugstr_w(hostname
), portnumber
);
361 hostnameU
= strWtoU( hostname
);
362 if (!hostnameU
) goto exit
;
365 hostnameU
= strWtoU( defaulthost
);
366 if (!hostnameU
) goto exit
;
369 url
= urlify_hostnames( "ldap://", hostnameU
, portnumber
);
372 ldap_initialize( &ld
, url
);
375 strfreeU( hostnameU
);
383 WLDAP32_LDAP
*ldap_sslinitA( PCHAR hostname
, ULONG portnumber
, int secure
)
387 WCHAR
*hostnameW
= NULL
;
389 TRACE( "(%s, %ld, 0x%08x)\n", debugstr_a(hostname
), portnumber
, secure
);
392 hostnameW
= strAtoW( hostname
);
393 if (!hostnameW
) return NULL
;
396 ld
= ldap_sslinitW( hostnameW
, portnumber
, secure
);
398 strfreeW( hostnameW
);
405 WLDAP32_LDAP
*ldap_sslinitW( PWCHAR hostname
, ULONG portnumber
, int secure
)
409 char *hostnameU
= NULL
, *url
= NULL
;
411 TRACE( "(%s, %ld, 0x%08x)\n", debugstr_w(hostname
), portnumber
, secure
);
414 hostnameU
= strWtoU( hostname
);
415 if (!hostnameU
) goto exit
;
418 hostnameU
= strWtoU( defaulthost
);
419 if (!hostnameU
) goto exit
;
423 url
= urlify_hostnames( "ldaps://", hostnameU
, portnumber
);
425 url
= urlify_hostnames( "ldap://", hostnameU
, portnumber
);
428 ldap_initialize( &ld
, url
);
431 strfreeU( hostnameU
);
439 ULONG
ldap_start_tls_sA( WLDAP32_LDAP
*ld
, PULONG retval
, WLDAP32_LDAPMessage
**result
,
440 PLDAPControlA
*serverctrls
, PLDAPControlA
*clientctrls
)
442 ULONG ret
= LDAP_NOT_SUPPORTED
;
444 LDAPControlW
**serverctrlsW
= NULL
, **clientctrlsW
= NULL
;
446 ret
= WLDAP32_LDAP_NO_MEMORY
;
448 TRACE( "(%p, %p, %p, %p, %p)\n", ld
, retval
, result
, serverctrls
, clientctrls
);
450 if (!ld
) return ~0UL;
453 serverctrlsW
= controlarrayAtoW( serverctrls
);
454 if (!serverctrlsW
) goto exit
;
457 clientctrlsW
= controlarrayAtoW( clientctrls
);
458 if (!clientctrlsW
) goto exit
;
461 ret
= ldap_start_tls_sW( ld
, retval
, result
, serverctrlsW
, clientctrlsW
);
464 controlarrayfreeW( serverctrlsW
);
465 controlarrayfreeW( clientctrlsW
);
471 ULONG
ldap_start_tls_sW( WLDAP32_LDAP
*ld
, PULONG retval
, WLDAP32_LDAPMessage
**result
,
472 PLDAPControlW
*serverctrls
, PLDAPControlW
*clientctrls
)
474 ULONG ret
= LDAP_NOT_SUPPORTED
;
476 LDAPControl
**serverctrlsU
= NULL
, **clientctrlsU
= NULL
;
478 ret
= WLDAP32_LDAP_NO_MEMORY
;
480 TRACE( "(%p, %p, %p, %p, %p)\n", ld
, retval
, result
, serverctrls
, clientctrls
);
482 if (!ld
) return ~0UL;
485 serverctrlsU
= controlarrayWtoU( serverctrls
);
486 if (!serverctrlsU
) goto exit
;
489 clientctrlsU
= controlarrayWtoU( clientctrls
);
490 if (!clientctrlsU
) goto exit
;
493 ret
= ldap_start_tls_s( ld
, serverctrlsU
, clientctrlsU
);
496 controlarrayfreeU( serverctrlsU
);
497 controlarrayfreeU( clientctrlsU
);
503 ULONG
ldap_startup( PLDAP_VERSION_INFO version
, HANDLE
*instance
)
505 TRACE( "(%p, %p)\n", version
, instance
);
509 BOOLEAN
ldap_stop_tls_s( WLDAP32_LDAP
*ld
)
511 TRACE( "(%p)\n", ld
);
512 return 0; /* FIXME: find a way to stop tls on a connection */