windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / wldap32 / init.c
blob44fc44ee485177019311e5df84901d2427b55760
1 /*
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
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnls.h"
26 #include "winternl.h"
27 #include "schannel.h"
28 #include "sspi.h"
30 #include "wine/debug.h"
31 #include "winldap_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
35 /* Split a space separated string of hostnames into a string array */
36 static char **split_hostnames( const char *hostnames )
38 char **res, *str, *p, *q;
39 unsigned int i = 0;
41 str = strdup( hostnames );
42 if (!str) return NULL;
44 p = str;
45 while (isspace( *p )) p++;
46 if (*p) i++;
48 while (*p)
50 if (isspace( *p ))
52 while (isspace( *p )) p++;
53 if (*p) i++;
55 p++;
58 if (!(res = malloc( (i + 1) * sizeof(char *) )))
60 free( str );
61 return NULL;
64 p = str;
65 while (isspace( *p )) p++;
67 q = p;
68 i = 0;
70 while (*p)
72 if (p[1] != '\0')
74 if (isspace( *p ))
76 *p = '\0'; p++;
77 res[i] = strdup( q );
78 if (!res[i]) goto oom;
79 i++;
81 while (isspace( *p )) p++;
82 q = p;
85 else
87 res[i] = strdup( q );
88 if (!res[i]) goto oom;
89 i++;
91 p++;
93 res[i] = NULL;
95 free( str );
96 return res;
98 oom:
99 while (i > 0) free( res[--i] );
100 free( res );
101 free( str );
102 return NULL;
105 /* Determine if a URL starts with a known LDAP scheme */
106 static BOOL has_ldap_scheme( char *url )
108 return !_strnicmp( url, "ldap://", 7 ) ||
109 !_strnicmp( url, "ldaps://", 8 ) ||
110 !_strnicmp( url, "ldapi://", 8 ) ||
111 !_strnicmp( url, "cldap://", 8 );
114 /* Flatten an array of hostnames into a space separated string of URLs.
115 * Prepend a given scheme and append a given port number to each hostname
116 * if necessary.
118 static char *join_hostnames( const char *scheme, char **hostnames, ULONG portnumber )
120 char *res, *p, *q, **v;
121 unsigned int i = 0, size = 0;
122 static const char sep[] = " ";
123 char port[7];
125 sprintf( port, ":%lu", portnumber );
127 for (v = hostnames; *v; v++)
129 if (!has_ldap_scheme( *v ))
131 size += strlen( scheme );
132 q = *v;
134 else
135 /* skip past colon in scheme prefix */
136 q = strchr( *v, '/' );
138 size += strlen( *v );
140 if (!strchr( q, ':' ))
141 size += strlen( port );
143 i++;
146 size += (i - 1) * strlen( sep );
147 if (!(res = malloc( size + 1 ))) return NULL;
149 p = res;
150 for (v = hostnames; *v; v++)
152 if (v != hostnames)
154 strcpy( p, sep );
155 p += strlen( sep );
158 if (!has_ldap_scheme( *v ))
160 strcpy( p, scheme );
161 p += strlen( scheme );
162 q = *v;
164 else
165 /* skip past colon in scheme prefix */
166 q = strchr( *v, '/' );
168 strcpy( p, *v );
169 p += strlen( *v );
171 if (!strchr( q, ':' ))
173 strcpy( p, port );
174 p += strlen( port );
177 return res;
180 static char *urlify_hostnames( const char *scheme, char *hostnames, ULONG port )
182 char *url = NULL, **strarray;
184 strarray = split_hostnames( hostnames );
185 if (strarray)
186 url = join_hostnames( scheme, strarray, port );
187 else
188 return NULL;
190 strarrayfreeU( strarray );
191 return url;
194 static LDAP *create_context( const char *url )
196 LDAP *ld;
197 int version = WLDAP32_LDAP_VERSION3;
199 if (!(ld = calloc( 1, sizeof( *ld )))) return NULL;
200 if (map_error( ldap_initialize( &CTX(ld), url ) ) == WLDAP32_LDAP_SUCCESS)
202 ldap_set_option( CTX(ld), WLDAP32_LDAP_OPT_PROTOCOL_VERSION, &version );
203 return ld;
205 free( ld );
206 return NULL;
209 /***********************************************************************
210 * cldap_openA (WLDAP32.@)
212 LDAP * CDECL cldap_openA( char *hostname, ULONG portnumber )
214 LDAP *ld;
215 WCHAR *hostnameW = NULL;
217 TRACE( "(%s, %lu)\n", debugstr_a(hostname), portnumber );
219 if (hostname && !(hostnameW = strAtoW( hostname ))) return NULL;
221 ld = cldap_openW( hostnameW, portnumber );
223 free( hostnameW );
224 return ld;
227 /***********************************************************************
228 * cldap_openW (WLDAP32.@)
230 LDAP * CDECL cldap_openW( WCHAR *hostname, ULONG portnumber )
232 LDAP *ld = NULL;
233 char *hostnameU, *url = NULL;
235 TRACE( "(%s, %lu)\n", debugstr_w(hostname), portnumber );
237 if (!(hostnameU = strWtoU( hostname ? hostname : L"localhost" ))) return NULL;
238 if (!(url = urlify_hostnames( "cldap://", hostnameU, portnumber ))) goto exit;
240 ld = create_context( url );
242 exit:
243 free( hostnameU );
244 free( url );
245 return ld;
248 /***********************************************************************
249 * ldap_connect (WLDAP32.@)
251 ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout )
253 QUERYCLIENTCERT *client_cert_callback = CLIENT_CERT_CALLBACK(ld);
254 VERIFYSERVERCERT *server_cert_callback = SERVER_CERT_CALLBACK(ld);
255 int ret;
257 TRACE( "(%p, %p)\n", ld, timeout );
259 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
260 if (CONNECTED(ld)) return WLDAP32_LDAP_SUCCESS;
262 if (client_cert_callback)
263 FIXME( "mTLS is not implemented\n" );
265 if (timeout && (timeout->tv_sec || timeout->tv_usec)) FIXME( "ignoring timeout\n" );
266 if ((ret = ldap_connect( CTX(ld) ))) return map_error( ret );
268 if (server_cert_callback)
270 CtxtHandle *tls_context;
271 const CERT_CONTEXT *cert;
273 if ((ret = ldap_get_option( CTX(ld), LDAP_OPT_X_TLS_SSL_CTX, &tls_context )))
274 return map_error( ret );
276 if (QueryContextAttributesA( tls_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &cert ) == SEC_E_OK)
278 if (server_cert_callback( ld, &cert ))
280 TRACE( "accepted\n" );
282 else
284 WARN( "rejected\n" );
285 return WLDAP32_LDAP_SERVER_DOWN;
290 CONNECTED(ld) = TRUE;
291 return WLDAP32_LDAP_SUCCESS;
294 /***********************************************************************
295 * ldap_initA (WLDAP32.@)
297 LDAP * CDECL ldap_initA( const PCHAR hostname, ULONG portnumber )
299 LDAP *ld;
300 WCHAR *hostnameW = NULL;
302 TRACE( "(%s, %lu)\n", debugstr_a(hostname), portnumber );
304 if (hostname && !(hostnameW = strAtoW( hostname ))) return NULL;
306 ld = ldap_initW( hostnameW, portnumber );
308 free( hostnameW );
309 return ld;
312 /***********************************************************************
313 * ldap_initW (WLDAP32.@)
315 LDAP * CDECL ldap_initW( const PWCHAR hostname, ULONG portnumber )
317 LDAP *ld = NULL;
318 char *hostnameU, *url = NULL;
320 TRACE( "(%s, %lu)\n", debugstr_w(hostname), portnumber );
322 if (!(hostnameU = strWtoU( hostname ? hostname : L"localhost" ))) return NULL;
323 if (!(url = urlify_hostnames( "ldap://", hostnameU, portnumber ))) goto exit;
325 ld = create_context( url );
327 exit:
328 free( hostnameU );
329 free( url );
330 return ld;
333 /***********************************************************************
334 * ldap_openA (WLDAP32.@)
336 LDAP * CDECL ldap_openA( char *hostname, ULONG portnumber )
338 LDAP *ld;
339 WCHAR *hostnameW = NULL;
341 TRACE( "(%s, %lu)\n", debugstr_a(hostname), portnumber );
343 if (hostname && !(hostnameW = strAtoW( hostname ))) return NULL;
345 ld = ldap_openW( hostnameW, portnumber );
347 free( hostnameW );
348 return ld;
351 /***********************************************************************
352 * ldap_openW (WLDAP32.@)
354 LDAP * CDECL ldap_openW( WCHAR *hostname, ULONG portnumber )
356 LDAP *ld = NULL;
357 char *hostnameU, *url = NULL;
359 TRACE( "(%s, %lu)\n", debugstr_w(hostname), portnumber );
361 if (!(hostnameU = strWtoU( hostname ? hostname : L"localhost" ))) return NULL;
362 if (!(url = urlify_hostnames( "ldap://", hostnameU, portnumber ))) goto exit;
364 ld = create_context( url );
366 exit:
367 free( hostnameU );
368 free( url );
369 return ld;
372 /***********************************************************************
373 * ldap_sslinitA (WLDAP32.@)
375 LDAP * CDECL ldap_sslinitA( char *hostname, ULONG portnumber, int secure )
377 LDAP *ld;
378 WCHAR *hostnameW = NULL;
380 TRACE( "(%s, %lu, %d)\n", debugstr_a(hostname), portnumber, secure );
382 if (hostname && !(hostnameW = strAtoW( hostname ))) return NULL;
384 ld = ldap_sslinitW( hostnameW, portnumber, secure );
386 free( hostnameW );
387 return ld;
390 /***********************************************************************
391 * ldap_sslinitW (WLDAP32.@)
393 LDAP * CDECL ldap_sslinitW( WCHAR *hostname, ULONG portnumber, int secure )
395 LDAP *ld = NULL;
396 char *hostnameU, *url = NULL;
398 TRACE( "(%s, %lu, %d)\n", debugstr_w(hostname), portnumber, secure );
400 if (!(hostnameU = strWtoU( hostname ? hostname : L"localhost" ))) return NULL;
402 if (secure)
403 url = urlify_hostnames( "ldaps://", hostnameU, portnumber );
404 else
405 url = urlify_hostnames( "ldap://", hostnameU, portnumber );
406 if (!url) goto exit;
408 ld = create_context( url );
410 exit:
411 free( hostnameU );
412 free( url );
413 return ld;
416 /***********************************************************************
417 * ldap_start_tls_sA (WLDAP32.@)
419 ULONG CDECL ldap_start_tls_sA( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlA **serverctrls,
420 LDAPControlA **clientctrls )
422 ULONG ret = WLDAP32_LDAP_NO_MEMORY;
423 LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
425 TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls );
427 if (!ld) return ~0u;
429 if (serverctrls && !(serverctrlsW = controlarrayAtoW( serverctrls ))) goto exit;
430 if (clientctrls && !(clientctrlsW = controlarrayAtoW( clientctrls ))) goto exit;
432 ret = ldap_start_tls_sW( ld, retval, result, serverctrlsW, clientctrlsW );
434 exit:
435 controlarrayfreeW( serverctrlsW );
436 controlarrayfreeW( clientctrlsW );
437 return ret;
440 /***********************************************************************
441 * ldap_start_tls_s (WLDAP32.@)
443 ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LDAPControlW **serverctrls,
444 LDAPControlW **clientctrls )
446 ULONG ret = WLDAP32_LDAP_NO_MEMORY;
447 LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
449 TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls );
450 if (result)
452 FIXME( "result message not supported\n" );
453 *result = NULL;
456 if (!ld) return ~0u;
457 if (CONNECTED(ld)) return WLDAP32_LDAP_LOCAL_ERROR;
459 if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit;
460 if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit;
462 ret = map_error( ldap_start_tls_s( CTX(ld), serverctrlsU, clientctrlsU ) );
464 exit:
465 controlarrayfreeU( serverctrlsU );
466 controlarrayfreeU( clientctrlsU );
467 return ret;
470 /***********************************************************************
471 * ldap_startup (WLDAP32.@)
473 ULONG CDECL ldap_startup( LDAP_VERSION_INFO *version, HANDLE *instance )
475 TRACE( "(%p, %p)\n", version, instance );
476 return WLDAP32_LDAP_SUCCESS;
479 /***********************************************************************
480 * ldap_stop_tls_s (WLDAP32.@)
482 BOOLEAN CDECL ldap_stop_tls_s( LDAP *ld )
484 TRACE( "(%p)\n", ld );
485 return TRUE; /* FIXME: find a way to stop tls on a connection */