remoteauth.c revision 1.1 1 1.1 christos /* $NetBSD: remoteauth.c,v 1.1 2021/08/14 16:05:24 christos Exp $ */
2 1.1 christos
3 1.1 christos /* $OpenLDAP$ */
4 1.1 christos /* remoteauth.c - Overlay to delegate bind processing to a remote server */
5 1.1 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 christos *
7 1.1 christos * Copyright 2004-2021 The OpenLDAP Foundation.
8 1.1 christos * Portions Copyright 2017-2021 Ondej Kuznk, Symas Corporation.
9 1.1 christos * Portions Copyright 2004-2017 Howard Chu, Symas Corporation.
10 1.1 christos * Portions Copyright 2004 Hewlett-Packard Company.
11 1.1 christos * All rights reserved.
12 1.1 christos *
13 1.1 christos * Redistribution and use in source and binary forms, with or without
14 1.1 christos * modification, are permitted only as authorized by the OpenLDAP
15 1.1 christos * Public License.
16 1.1 christos *
17 1.1 christos * A copy of this license is available in the file LICENSE in the
18 1.1 christos * top-level directory of the distribution or, alternatively, at
19 1.1 christos * <http://www.OpenLDAP.org/license.html>.
20 1.1 christos */
21 1.1 christos
22 1.1 christos #include <sys/cdefs.h>
23 1.1 christos __RCSID("$NetBSD: remoteauth.c,v 1.1 2021/08/14 16:05:24 christos Exp $");
24 1.1 christos
25 1.1 christos #include "portable.h"
26 1.1 christos
27 1.1 christos #include <ldap.h>
28 1.1 christos #if SLAPD_MODULES
29 1.1 christos #define LIBLTDL_DLL_IMPORT /* Win32: don't re-export libltdl's symbols */
30 1.1 christos #include <ltdl.h>
31 1.1 christos #endif
32 1.1 christos #include <ac/errno.h>
33 1.1 christos #include <ac/time.h>
34 1.1 christos #include <ac/string.h>
35 1.1 christos #include <ac/ctype.h>
36 1.1 christos #include "lutil.h"
37 1.1 christos #include "slap.h"
38 1.1 christos #include "slap-config.h"
39 1.1 christos
40 1.1 christos #ifndef UP_STR
41 1.1 christos #define UP_STR "userPassword"
42 1.1 christos #endif /* UP_STR */
43 1.1 christos
44 1.1 christos #ifndef LDAP_PREFIX
45 1.1 christos #define LDAP_PREFIX "ldap://"
46 1.1 christos #endif /* LDAP_PREFIX */
47 1.1 christos
48 1.1 christos #ifndef FILE_PREFIX
49 1.1 christos #define FILE_PREFIX "file://"
50 1.1 christos #endif /* LDAP_PREFIX */
51 1.1 christos
52 1.1 christos typedef struct _ad_info {
53 1.1 christos struct _ad_info *next;
54 1.1 christos char *domain;
55 1.1 christos char *realm;
56 1.1 christos } ad_info;
57 1.1 christos
58 1.1 christos typedef struct _ad_pin {
59 1.1 christos struct _ad_pin *next;
60 1.1 christos char *hostname;
61 1.1 christos char *pin;
62 1.1 christos } ad_pin;
63 1.1 christos
64 1.1 christos typedef struct _ad_private {
65 1.1 christos char *dn;
66 1.1 christos AttributeDescription *dn_ad;
67 1.1 christos char *domain_attr;
68 1.1 christos AttributeDescription *domain_ad;
69 1.1 christos
70 1.1 christos AttributeDescription *up_ad;
71 1.1 christos ad_info *mappings;
72 1.1 christos
73 1.1 christos char *default_realm;
74 1.1 christos char *default_domain;
75 1.1 christos
76 1.1 christos int up_set;
77 1.1 christos int retry_count;
78 1.1 christos int store_on_success;
79 1.1 christos
80 1.1 christos ad_pin *pins;
81 1.1 christos slap_bindconf ad_tls;
82 1.1 christos } ad_private;
83 1.1 christos
84 1.1 christos enum {
85 1.1 christos REMOTE_AUTH_MAPPING = 1,
86 1.1 christos REMOTE_AUTH_DN_ATTRIBUTE,
87 1.1 christos REMOTE_AUTH_DOMAIN_ATTRIBUTE,
88 1.1 christos REMOTE_AUTH_DEFAULT_DOMAIN,
89 1.1 christos REMOTE_AUTH_DEFAULT_REALM,
90 1.1 christos REMOTE_AUTH_CACERT_DIR,
91 1.1 christos REMOTE_AUTH_CACERT_FILE,
92 1.1 christos REMOTE_AUTH_VALIDATE_CERTS,
93 1.1 christos REMOTE_AUTH_RETRY_COUNT,
94 1.1 christos REMOTE_AUTH_TLS,
95 1.1 christos REMOTE_AUTH_TLS_PIN,
96 1.1 christos REMOTE_AUTH_STORE_ON_SUCCESS,
97 1.1 christos };
98 1.1 christos
99 1.1 christos static ConfigDriver remoteauth_cf_gen;
100 1.1 christos
101 1.1 christos static ConfigTable remoteauthcfg[] = {
102 1.1 christos { "remoteauth_mapping", "mapping between domain and realm", 2, 3, 0,
103 1.1 christos ARG_MAGIC|REMOTE_AUTH_MAPPING,
104 1.1 christos remoteauth_cf_gen,
105 1.1 christos "( OLcfgOvAt:24.1 NAME 'olcRemoteAuthMapping' "
106 1.1 christos "DESC 'Mapping from domain name to server' "
107 1.1 christos "SYNTAX OMsDirectoryString )",
108 1.1 christos NULL, NULL
109 1.1 christos },
110 1.1 christos { "remoteauth_dn_attribute", "Attribute to use as AD bind DN", 2, 2, 0,
111 1.1 christos ARG_MAGIC|REMOTE_AUTH_DN_ATTRIBUTE,
112 1.1 christos remoteauth_cf_gen,
113 1.1 christos "( OLcfgOvAt:24.2 NAME 'olcRemoteAuthDNAttribute' "
114 1.1 christos "DESC 'Attribute in entry to use as bind DN for AD' "
115 1.1 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
116 1.1 christos NULL, NULL
117 1.1 christos },
118 1.1 christos { "remoteauth_domain_attribute", "Attribute to use as domain determinant", 2, 2, 0,
119 1.1 christos ARG_MAGIC|REMOTE_AUTH_DOMAIN_ATTRIBUTE,
120 1.1 christos remoteauth_cf_gen,
121 1.1 christos "( OLcfgOvAt:24.3 NAME 'olcRemoteAuthDomainAttribute' "
122 1.1 christos "DESC 'Attribute in entry to determine windows domain' "
123 1.1 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
124 1.1 christos NULL, NULL
125 1.1 christos },
126 1.1 christos { "remoteauth_default_domain", "Default Windows domain", 2, 2, 0,
127 1.1 christos ARG_MAGIC|REMOTE_AUTH_DEFAULT_DOMAIN,
128 1.1 christos remoteauth_cf_gen,
129 1.1 christos "( OLcfgOvAt:24.4 NAME 'olcRemoteAuthDefaultDomain' "
130 1.1 christos "DESC 'Default Windows domain to use' "
131 1.1 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
132 1.1 christos NULL, NULL
133 1.1 christos },
134 1.1 christos { "remoteauth_default_realm", "Default AD realm", 2, 2, 0,
135 1.1 christos ARG_MAGIC|REMOTE_AUTH_DEFAULT_REALM,
136 1.1 christos remoteauth_cf_gen,
137 1.1 christos "( OLcfgOvAt:24.5 NAME 'olcRemoteAuthDefaultRealm' "
138 1.1 christos "DESC 'Default AD realm to use' "
139 1.1 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
140 1.1 christos NULL, NULL
141 1.1 christos },
142 1.1 christos { "remoteauth_store", "on|off", 1, 2, 0,
143 1.1 christos ARG_OFFSET|ARG_ON_OFF|REMOTE_AUTH_STORE_ON_SUCCESS,
144 1.1 christos (void *)offsetof(ad_private, store_on_success),
145 1.1 christos "( OLcfgOvAt:24.6 NAME 'olcRemoteAuthStore' "
146 1.1 christos "DESC 'Store password locally on success' "
147 1.1 christos "SYNTAX OMsBoolean SINGLE-VALUE )",
148 1.1 christos NULL, NULL
149 1.1 christos },
150 1.1 christos { "remoteauth_retry_count", "integer", 2, 2, 0,
151 1.1 christos ARG_OFFSET|ARG_UINT|REMOTE_AUTH_RETRY_COUNT,
152 1.1 christos (void *)offsetof(ad_private, retry_count),
153 1.1 christos "( OLcfgOvAt:24.7 NAME 'olcRemoteAuthRetryCount' "
154 1.1 christos "DESC 'Number of retries attempted' "
155 1.1 christos "SYNTAX OMsInteger SINGLE-VALUE )",
156 1.1 christos NULL, { .v_uint = 3 }
157 1.1 christos },
158 1.1 christos { "remoteauth_tls", "tls settings", 2, 0, 0,
159 1.1 christos ARG_MAGIC|REMOTE_AUTH_TLS,
160 1.1 christos remoteauth_cf_gen,
161 1.1 christos "( OLcfgOvAt:24.8 NAME 'olcRemoteAuthTLS' "
162 1.1 christos "DESC 'StartTLS settings' "
163 1.1 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
164 1.1 christos NULL, NULL
165 1.1 christos },
166 1.1 christos { "remoteauth_tls_peerkey_hash", "mapping between hostnames and their public key hash", 3, 3, 0,
167 1.1 christos ARG_MAGIC|REMOTE_AUTH_TLS_PIN,
168 1.1 christos remoteauth_cf_gen,
169 1.1 christos "( OLcfgOvAt:24.9 NAME 'olcRemoteAuthTLSPeerkeyHash' "
170 1.1 christos "DESC 'StartTLS hostname to public key pin mapping file' "
171 1.1 christos "SYNTAX OMsDirectoryString )",
172 1.1 christos NULL, NULL
173 1.1 christos },
174 1.1 christos
175 1.1 christos { NULL, NULL, 0, 0, 0, ARG_IGNORED, NULL }
176 1.1 christos };
177 1.1 christos
178 1.1 christos static ConfigOCs remoteauthocs[] = {
179 1.1 christos { "( OLcfgOvOc:24.1 "
180 1.1 christos "NAME 'olcRemoteAuthCfg' "
181 1.1 christos "DESC 'Remote Directory passthough authentication configuration' "
182 1.1 christos "SUP olcOverlayConfig "
183 1.1 christos "MUST olcRemoteAuthTLS "
184 1.1 christos "MAY ( olcRemoteAuthMapping $ olcRemoteAuthDNAttribute $ "
185 1.1 christos " olcRemoteAuthDomainAttribute $ olcRemoteAuthDefaultDomain $ "
186 1.1 christos " olcRemoteAuthDefaultRealm $ olcRemoteAuthStore $ "
187 1.1 christos " olcRemoteAuthRetryCount $ olcRemoteAuthTLSPeerkeyHash ) )",
188 1.1 christos Cft_Overlay, remoteauthcfg },
189 1.1 christos { NULL, 0, NULL }
190 1.1 christos };
191 1.1 christos
192 1.1 christos static int
193 1.1 christos remoteauth_cf_gen( ConfigArgs *c )
194 1.1 christos {
195 1.1 christos slap_overinst *on = (slap_overinst *)c->bi;
196 1.1 christos ad_private *ad = (ad_private *)on->on_bi.bi_private;
197 1.1 christos struct berval bv;
198 1.1 christos int i, rc = 0;
199 1.1 christos ad_info *map;
200 1.1 christos const char *text = NULL;
201 1.1 christos
202 1.1 christos switch ( c->op ) {
203 1.1 christos case SLAP_CONFIG_EMIT:
204 1.1 christos switch ( c->type ) {
205 1.1 christos case REMOTE_AUTH_MAPPING:
206 1.1 christos for ( map = ad->mappings; map; map = map->next ) {
207 1.1 christos char *str;
208 1.1 christos
209 1.1 christos str = ch_malloc( strlen( map->domain ) +
210 1.1 christos strlen( map->realm ) + 2 );
211 1.1 christos sprintf( str, "%s %s", map->domain, map->realm );
212 1.1 christos ber_str2bv( str, strlen( str ), 1, &bv );
213 1.1 christos ch_free( str );
214 1.1 christos rc = value_add_one( &c->rvalue_vals, &bv );
215 1.1 christos if ( rc ) return rc;
216 1.1 christos rc = value_add_one( &c->rvalue_nvals, &bv );
217 1.1 christos if ( rc ) return rc;
218 1.1 christos }
219 1.1 christos break;
220 1.1 christos case REMOTE_AUTH_DN_ATTRIBUTE:
221 1.1 christos if ( ad->dn )
222 1.1 christos value_add_one( &c->rvalue_vals, &ad->dn_ad->ad_cname );
223 1.1 christos break;
224 1.1 christos case REMOTE_AUTH_DOMAIN_ATTRIBUTE:
225 1.1 christos if ( ad->domain_attr )
226 1.1 christos value_add_one(
227 1.1 christos &c->rvalue_vals, &ad->domain_ad->ad_cname );
228 1.1 christos break;
229 1.1 christos case REMOTE_AUTH_DEFAULT_DOMAIN:
230 1.1 christos if ( ad->default_domain ) {
231 1.1 christos ber_str2bv( ad->default_domain, 0, 1, &bv );
232 1.1 christos value_add_one( &c->rvalue_vals, &bv );
233 1.1 christos }
234 1.1 christos break;
235 1.1 christos case REMOTE_AUTH_DEFAULT_REALM:
236 1.1 christos if ( ad->default_realm ) {
237 1.1 christos ber_str2bv( ad->default_realm, 0, 1, &bv );
238 1.1 christos value_add_one( &c->rvalue_vals, &bv );
239 1.1 christos }
240 1.1 christos break;
241 1.1 christos case REMOTE_AUTH_TLS:
242 1.1 christos bindconf_tls_unparse( &ad->ad_tls, &bv );
243 1.1 christos
244 1.1 christos for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
245 1.1 christos /* count spaces */ ;
246 1.1 christos
247 1.1 christos if ( i ) {
248 1.1 christos bv.bv_len -= i;
249 1.1 christos AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
250 1.1 christos bv.bv_len + 1 );
251 1.1 christos }
252 1.1 christos
253 1.1 christos value_add_one( &c->rvalue_vals, &bv );
254 1.1 christos break;
255 1.1 christos case REMOTE_AUTH_TLS_PIN: {
256 1.1 christos ad_pin *pin = ad->pins;
257 1.1 christos for ( pin = ad->pins; pin; pin = pin->next ) {
258 1.1 christos bv.bv_val = ch_malloc( strlen( pin->hostname ) +
259 1.1 christos strlen( pin->pin ) + 2 );
260 1.1 christos bv.bv_len = sprintf(
261 1.1 christos bv.bv_val, "%s %s", pin->hostname, pin->pin );
262 1.1 christos rc = value_add_one( &c->rvalue_vals, &bv );
263 1.1 christos if ( rc ) return rc;
264 1.1 christos rc = value_add_one( &c->rvalue_nvals, &bv );
265 1.1 christos if ( rc ) return rc;
266 1.1 christos }
267 1.1 christos } break;
268 1.1 christos
269 1.1 christos default:
270 1.1 christos abort();
271 1.1 christos }
272 1.1 christos break;
273 1.1 christos case LDAP_MOD_DELETE:
274 1.1 christos switch ( c->type ) {
275 1.1 christos case REMOTE_AUTH_MAPPING:
276 1.1 christos if ( c->valx < 0 ) {
277 1.1 christos /* delete all mappings */
278 1.1 christos while ( ad->mappings ) {
279 1.1 christos map = ad->mappings;
280 1.1 christos ad->mappings = ad->mappings->next;
281 1.1 christos ch_free( map->domain );
282 1.1 christos ch_free( map->realm );
283 1.1 christos ch_free( map );
284 1.1 christos }
285 1.1 christos } else {
286 1.1 christos /* delete a specific mapping indicated by 'valx'*/
287 1.1 christos ad_info *pmap = NULL;
288 1.1 christos
289 1.1 christos for ( map = ad->mappings, i = 0;
290 1.1 christos ( map ) && ( i < c->valx );
291 1.1 christos pmap = map, map = map->next, i++ )
292 1.1 christos ;
293 1.1 christos
294 1.1 christos if ( pmap ) {
295 1.1 christos pmap->next = map->next;
296 1.1 christos map->next = NULL;
297 1.1 christos
298 1.1 christos ch_free( map->domain );
299 1.1 christos ch_free( map->realm );
300 1.1 christos ch_free( map );
301 1.1 christos } else if ( ad->mappings ) {
302 1.1 christos /* delete the first item in the list */
303 1.1 christos map = ad->mappings;
304 1.1 christos ad->mappings = map->next;
305 1.1 christos ch_free( map->domain );
306 1.1 christos ch_free( map->realm );
307 1.1 christos ch_free( map );
308 1.1 christos }
309 1.1 christos }
310 1.1 christos break;
311 1.1 christos case REMOTE_AUTH_DN_ATTRIBUTE:
312 1.1 christos if ( ad->dn ) {
313 1.1 christos ch_free( ad->dn );
314 1.1 christos ad->dn = NULL; /* Don't free AttributeDescription */
315 1.1 christos }
316 1.1 christos break;
317 1.1 christos case REMOTE_AUTH_DOMAIN_ATTRIBUTE:
318 1.1 christos if ( ad->domain_attr ) {
319 1.1 christos ch_free( ad->domain_attr );
320 1.1 christos /* Don't free AttributeDescription */
321 1.1 christos ad->domain_attr = NULL;
322 1.1 christos }
323 1.1 christos break;
324 1.1 christos case REMOTE_AUTH_DEFAULT_DOMAIN:
325 1.1 christos if ( ad->default_domain ) {
326 1.1 christos ch_free( ad->default_domain );
327 1.1 christos ad->default_domain = NULL;
328 1.1 christos }
329 1.1 christos break;
330 1.1 christos case REMOTE_AUTH_DEFAULT_REALM:
331 1.1 christos if ( ad->default_realm ) {
332 1.1 christos ch_free( ad->default_realm );
333 1.1 christos ad->default_realm = NULL;
334 1.1 christos }
335 1.1 christos break;
336 1.1 christos case REMOTE_AUTH_TLS:
337 1.1 christos /* MUST + SINGLE-VALUE -> this is a replace */
338 1.1 christos bindconf_free( &ad->ad_tls );
339 1.1 christos break;
340 1.1 christos case REMOTE_AUTH_TLS_PIN:
341 1.1 christos while ( ad->pins ) {
342 1.1 christos ad_pin *pin = ad->pins;
343 1.1 christos ad->pins = ad->pins->next;
344 1.1 christos ch_free( pin->hostname );
345 1.1 christos ch_free( pin->pin );
346 1.1 christos ch_free( pin );
347 1.1 christos }
348 1.1 christos break;
349 1.1 christos /* ARG_OFFSET */
350 1.1 christos case REMOTE_AUTH_STORE_ON_SUCCESS:
351 1.1 christos case REMOTE_AUTH_RETRY_COUNT:
352 1.1 christos abort();
353 1.1 christos break;
354 1.1 christos default:
355 1.1 christos abort();
356 1.1 christos }
357 1.1 christos break;
358 1.1 christos case SLAP_CONFIG_ADD:
359 1.1 christos case LDAP_MOD_ADD:
360 1.1 christos switch ( c->type ) {
361 1.1 christos case REMOTE_AUTH_MAPPING:
362 1.1 christos /* add mapping to head of list */
363 1.1 christos map = ch_malloc( sizeof(ad_info) );
364 1.1 christos map->domain = ber_strdup( c->argv[1] );
365 1.1 christos map->realm = ber_strdup( c->argv[2] );
366 1.1 christos map->next = ad->mappings;
367 1.1 christos ad->mappings = map;
368 1.1 christos
369 1.1 christos break;
370 1.1 christos case REMOTE_AUTH_DN_ATTRIBUTE:
371 1.1 christos if ( slap_str2ad( c->argv[1], &ad->dn_ad, &text ) ==
372 1.1 christos LDAP_SUCCESS ) {
373 1.1 christos ad->dn = ber_strdup( ad->dn_ad->ad_cname.bv_val );
374 1.1 christos } else {
375 1.1 christos strncpy( c->cr_msg, text, sizeof(c->cr_msg) );
376 1.1 christos c->cr_msg[sizeof(c->cr_msg) - 1] = '\0';
377 1.1 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
378 1.1 christos rc = ARG_BAD_CONF;
379 1.1 christos }
380 1.1 christos break;
381 1.1 christos case REMOTE_AUTH_DOMAIN_ATTRIBUTE:
382 1.1 christos if ( slap_str2ad( c->argv[1], &ad->domain_ad, &text ) ==
383 1.1 christos LDAP_SUCCESS ) {
384 1.1 christos ad->domain_attr =
385 1.1 christos ber_strdup( ad->domain_ad->ad_cname.bv_val );
386 1.1 christos } else {
387 1.1 christos strncpy( c->cr_msg, text, sizeof(c->cr_msg) );
388 1.1 christos c->cr_msg[sizeof(c->cr_msg) - 1] = '\0';
389 1.1 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
390 1.1 christos rc = ARG_BAD_CONF;
391 1.1 christos }
392 1.1 christos break;
393 1.1 christos case REMOTE_AUTH_DEFAULT_DOMAIN:
394 1.1 christos if ( ad->default_domain ) {
395 1.1 christos ch_free( ad->default_domain );
396 1.1 christos ad->default_domain = NULL;
397 1.1 christos }
398 1.1 christos ad->default_domain = ber_strdup( c->argv[1] );
399 1.1 christos break;
400 1.1 christos case REMOTE_AUTH_DEFAULT_REALM:
401 1.1 christos if ( ad->default_realm ) {
402 1.1 christos ch_free( ad->default_realm );
403 1.1 christos ad->default_realm = NULL;
404 1.1 christos }
405 1.1 christos ad->default_realm = ber_strdup( c->argv[1] );
406 1.1 christos break;
407 1.1 christos case REMOTE_AUTH_TLS:
408 1.1 christos for ( i=1; i < c->argc; i++ ) {
409 1.1 christos if ( bindconf_tls_parse( c->argv[i], &ad->ad_tls ) ) {
410 1.1 christos rc = 1;
411 1.1 christos break;
412 1.1 christos }
413 1.1 christos }
414 1.1 christos bindconf_tls_defaults( &ad->ad_tls );
415 1.1 christos break;
416 1.1 christos case REMOTE_AUTH_TLS_PIN: {
417 1.1 christos ad_pin *pin = ch_calloc( 1, sizeof(ad_pin) );
418 1.1 christos
419 1.1 christos pin->hostname = ber_strdup( c->argv[1] );
420 1.1 christos pin->pin = ber_strdup( c->argv[2] );
421 1.1 christos pin->next = ad->pins;
422 1.1 christos ad->pins = pin;
423 1.1 christos } break;
424 1.1 christos /* ARG_OFFSET */
425 1.1 christos case REMOTE_AUTH_STORE_ON_SUCCESS:
426 1.1 christos case REMOTE_AUTH_RETRY_COUNT:
427 1.1 christos abort();
428 1.1 christos break;
429 1.1 christos default:
430 1.1 christos abort();
431 1.1 christos }
432 1.1 christos break;
433 1.1 christos default:
434 1.1 christos abort();
435 1.1 christos }
436 1.1 christos
437 1.1 christos return rc;
438 1.1 christos }
439 1.1 christos
440 1.1 christos static char *
441 1.1 christos get_realm(
442 1.1 christos const char *domain,
443 1.1 christos ad_info *mappings,
444 1.1 christos const char *default_realm,
445 1.1 christos int *isfile )
446 1.1 christos {
447 1.1 christos ad_info *ai;
448 1.1 christos char *dom = NULL, *ch, *ret = NULL;
449 1.1 christos
450 1.1 christos if ( isfile ) *isfile = 0;
451 1.1 christos
452 1.1 christos if ( !domain ) {
453 1.1 christos ret = default_realm ? ch_strdup( default_realm ) : NULL;
454 1.1 christos goto exit;
455 1.1 christos }
456 1.1 christos
457 1.1 christos /* munge any DOMAIN\user or DOMAIN:user values into just DOMAIN */
458 1.1 christos
459 1.1 christos ch = strchr( domain, '\\' );
460 1.1 christos if ( !ch ) ch = strchr( domain, ':' );
461 1.1 christos
462 1.1 christos if ( ch ) {
463 1.1 christos dom = ch_malloc( ch - domain + 1 );
464 1.1 christos strncpy( dom, domain, ch - domain );
465 1.1 christos dom[ch - domain] = '\0';
466 1.1 christos } else {
467 1.1 christos dom = ch_strdup( domain );
468 1.1 christos }
469 1.1 christos
470 1.1 christos for ( ai = mappings; ai; ai = ai->next )
471 1.1 christos if ( strcasecmp( ai->domain, dom ) == 0 ) {
472 1.1 christos ret = ch_strdup( ai->realm );
473 1.1 christos break;
474 1.1 christos }
475 1.1 christos
476 1.1 christos if ( !ai )
477 1.1 christos ret = default_realm ? ch_strdup( default_realm ) :
478 1.1 christos NULL; /* no mapping found */
479 1.1 christos exit:
480 1.1 christos if ( dom ) ch_free( dom );
481 1.1 christos if ( ret &&
482 1.1 christos ( strncasecmp( ret, FILE_PREFIX, strlen( FILE_PREFIX ) ) == 0 ) ) {
483 1.1 christos char *p;
484 1.1 christos
485 1.1 christos p = ret;
486 1.1 christos ret = ch_strdup( p + strlen( FILE_PREFIX ) );
487 1.1 christos ch_free( p );
488 1.1 christos if ( isfile ) *isfile = 1;
489 1.1 christos }
490 1.1 christos
491 1.1 christos return ret;
492 1.1 christos }
493 1.1 christos
494 1.1 christos static char *
495 1.1 christos get_ldap_url( const char *realm, int isfile )
496 1.1 christos {
497 1.1 christos char *ldap_url = NULL;
498 1.1 christos FILE *fp;
499 1.1 christos
500 1.1 christos if ( !realm ) return NULL;
501 1.1 christos
502 1.1 christos if ( !isfile ) {
503 1.1 christos if ( strstr( realm, "://" ) ) {
504 1.1 christos return ch_strdup( realm );
505 1.1 christos }
506 1.1 christos
507 1.1 christos ldap_url = ch_malloc( 1 + strlen( LDAP_PREFIX ) + strlen( realm ) );
508 1.1 christos sprintf( ldap_url, "%s%s", LDAP_PREFIX, realm );
509 1.1 christos return ldap_url;
510 1.1 christos }
511 1.1 christos
512 1.1 christos fp = fopen( realm, "r" );
513 1.1 christos if ( !fp ) {
514 1.1 christos char ebuf[128];
515 1.1 christos int saved_errno = errno;
516 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth: "
517 1.1 christos "Unable to open realm file (%s)\n",
518 1.1 christos sock_errstr( saved_errno, ebuf, sizeof(ebuf) ) );
519 1.1 christos return NULL;
520 1.1 christos }
521 1.1 christos /*
522 1.1 christos * Read each line in the file and return a URL of the form
523 1.1 christos * "ldap://<line1> ldap://<line2> ... ldap://<lineN>"
524 1.1 christos * which can be passed to ldap_initialize.
525 1.1 christos */
526 1.1 christos while ( !feof( fp ) ) {
527 1.1 christos char line[512], *p;
528 1.1 christos
529 1.1 christos p = fgets( line, sizeof(line), fp );
530 1.1 christos if ( !p ) continue;
531 1.1 christos
532 1.1 christos /* terminate line at first whitespace */
533 1.1 christos for ( p = line; *p; p++ )
534 1.1 christos if ( isspace( *p ) ) {
535 1.1 christos *p = '\0';
536 1.1 christos break;
537 1.1 christos }
538 1.1 christos
539 1.1 christos if ( ldap_url ) {
540 1.1 christos char *nu;
541 1.1 christos
542 1.1 christos nu = ch_malloc( strlen( ldap_url ) + 2 + strlen( LDAP_PREFIX ) +
543 1.1 christos strlen( line ) );
544 1.1 christos
545 1.1 christos if ( strstr( line, "://" ) ) {
546 1.1 christos sprintf( nu, "%s %s", ldap_url, line );
547 1.1 christos } else {
548 1.1 christos sprintf( nu, "%s %s%s", ldap_url, LDAP_PREFIX, line );
549 1.1 christos }
550 1.1 christos ch_free( ldap_url );
551 1.1 christos ldap_url = nu;
552 1.1 christos } else {
553 1.1 christos ldap_url = ch_malloc( 1 + strlen( line ) + strlen( LDAP_PREFIX ) );
554 1.1 christos if ( strstr( line, "://" ) ) {
555 1.1 christos strcpy( ldap_url, line );
556 1.1 christos } else {
557 1.1 christos sprintf( ldap_url, "%s%s", LDAP_PREFIX, line );
558 1.1 christos }
559 1.1 christos }
560 1.1 christos }
561 1.1 christos
562 1.1 christos fclose( fp );
563 1.1 christos
564 1.1 christos return ldap_url;
565 1.1 christos }
566 1.1 christos
567 1.1 christos static void
568 1.1 christos trace_remoteauth_parameters( ad_private *ap )
569 1.1 christos {
570 1.1 christos ad_info *pad_info;
571 1.1 christos struct berval bv;
572 1.1 christos
573 1.1 christos if ( !ap ) return;
574 1.1 christos
575 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_dn_attribute: %s\n",
576 1.1 christos ap->dn ? ap->dn : "NULL" );
577 1.1 christos
578 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_domain_attribute: %s\n",
579 1.1 christos ap->domain_attr ? ap->domain_attr : "NULL" );
580 1.1 christos
581 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_default_realm: %s\n",
582 1.1 christos ap->default_realm ? ap->default_realm : "NULL" );
583 1.1 christos
584 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_default_domain: %s\n",
585 1.1 christos ap->default_domain ? ap->default_domain : "NULL" );
586 1.1 christos
587 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_retry_count: %d\n", ap->retry_count );
588 1.1 christos
589 1.1 christos bindconf_tls_unparse( &ap->ad_tls, &bv );
590 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_tls:%s\n", bv.bv_val );
591 1.1 christos ch_free( bv.bv_val );
592 1.1 christos
593 1.1 christos pad_info = ap->mappings;
594 1.1 christos while ( pad_info ) {
595 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_mappings(%s,%s)\n",
596 1.1 christos pad_info->domain ? pad_info->domain : "NULL",
597 1.1 christos pad_info->realm ? pad_info->realm : "NULL" );
598 1.1 christos pad_info = pad_info->next;
599 1.1 christos }
600 1.1 christos
601 1.1 christos return;
602 1.1 christos }
603 1.1 christos
604 1.1 christos static int
605 1.1 christos remoteauth_conn_cb(
606 1.1 christos LDAP *ld,
607 1.1 christos Sockbuf *sb,
608 1.1 christos LDAPURLDesc *srv,
609 1.1 christos struct sockaddr *addr,
610 1.1 christos struct ldap_conncb *ctx )
611 1.1 christos {
612 1.1 christos ad_private *ap = ctx->lc_arg;
613 1.1 christos ad_pin *pin = NULL;
614 1.1 christos char *host;
615 1.1 christos
616 1.1 christos host = srv->lud_host;
617 1.1 christos if ( !host || !*host ) {
618 1.1 christos host = "localhost";
619 1.1 christos }
620 1.1 christos
621 1.1 christos for ( pin = ap->pins; pin; pin = pin->next ) {
622 1.1 christos if ( !strcasecmp( host, pin->hostname ) ) break;
623 1.1 christos }
624 1.1 christos
625 1.1 christos if ( pin ) {
626 1.1 christos int rc = ldap_set_option( ld, LDAP_OPT_X_TLS_PEERKEY_HASH, pin->pin );
627 1.1 christos if ( rc == LDAP_SUCCESS ) {
628 1.1 christos return 0;
629 1.1 christos }
630 1.1 christos
631 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_conn_cb: "
632 1.1 christos "TLS Peerkey hash could not be set to '%s': %d\n",
633 1.1 christos pin->pin, rc );
634 1.1 christos } else {
635 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_conn_cb: "
636 1.1 christos "No TLS Peerkey hash found for host '%s'\n",
637 1.1 christos host );
638 1.1 christos }
639 1.1 christos
640 1.1 christos return -1;
641 1.1 christos }
642 1.1 christos
643 1.1 christos static void
644 1.1 christos remoteauth_conn_delcb( LDAP *ld, Sockbuf *sb, struct ldap_conncb *ctx )
645 1.1 christos {
646 1.1 christos return;
647 1.1 christos }
648 1.1 christos
649 1.1 christos static int
650 1.1 christos remoteauth_bind( Operation *op, SlapReply *rs )
651 1.1 christos {
652 1.1 christos Entry *e;
653 1.1 christos int rc;
654 1.1 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
655 1.1 christos ad_private *ap = (ad_private *)on->on_bi.bi_private;
656 1.1 christos Attribute *a_dom, *a_dn;
657 1.1 christos struct ldap_conncb ad_conncb = { .lc_add = remoteauth_conn_cb,
658 1.1 christos .lc_del = remoteauth_conn_delcb,
659 1.1 christos .lc_arg = ap };
660 1.1 christos struct berval dn = { 0 };
661 1.1 christos char *dom_val, *realm = NULL;
662 1.1 christos char *ldap_url = NULL;
663 1.1 christos LDAP *ld = NULL;
664 1.1 christos int protocol = LDAP_VERSION3, isfile = 0;
665 1.1 christos int tries = 0;
666 1.1 christos
667 1.1 christos if ( LogTest( LDAP_DEBUG_TRACE ) ) {
668 1.1 christos trace_remoteauth_parameters( ap );
669 1.1 christos }
670 1.1 christos
671 1.1 christos if ( op->orb_method != LDAP_AUTH_SIMPLE )
672 1.1 christos return SLAP_CB_CONTINUE; /* only do password auth */
673 1.1 christos
674 1.1 christos /* Can't handle root via this mechanism */
675 1.1 christos if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) return SLAP_CB_CONTINUE;
676 1.1 christos
677 1.1 christos if ( !ap->up_set ) {
678 1.1 christos const char *txt = NULL;
679 1.1 christos
680 1.1 christos if ( slap_str2ad( UP_STR, &ap->up_ad, &txt ) )
681 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: "
682 1.1 christos "userPassword attr undefined: %s\n",
683 1.1 christos txt ? txt : "" );
684 1.1 christos ap->up_set = 1;
685 1.1 christos }
686 1.1 christos
687 1.1 christos if ( !ap->up_ad ) {
688 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: "
689 1.1 christos "password attribute not configured\n" );
690 1.1 christos return SLAP_CB_CONTINUE; /* userPassword not defined */
691 1.1 christos }
692 1.1 christos
693 1.1 christos if ( !ap->dn ) {
694 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: "
695 1.1 christos "remote DN attribute not configured\n" );
696 1.1 christos return SLAP_CB_CONTINUE; /* no mapped DN attribute */
697 1.1 christos }
698 1.1 christos
699 1.1 christos if ( !ap->domain_attr ) {
700 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: "
701 1.1 christos "domain attribute not configured\n" );
702 1.1 christos return SLAP_CB_CONTINUE; /* no way to know domain */
703 1.1 christos }
704 1.1 christos
705 1.1 christos op->o_bd->bd_info = (BackendInfo *)on->on_info;
706 1.1 christos rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
707 1.1 christos if ( rc != LDAP_SUCCESS ) return SLAP_CB_CONTINUE;
708 1.1 christos
709 1.1 christos rc = SLAP_CB_CONTINUE;
710 1.1 christos /* if userPassword is defined in entry, skip to the end */
711 1.1 christos if ( attr_find( e->e_attrs, ap->up_ad ) ) {
712 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
713 1.1 christos "user has a password, skipping\n",
714 1.1 christos op->o_log_prefix );
715 1.1 christos goto exit;
716 1.1 christos }
717 1.1 christos
718 1.1 christos a_dom = attr_find( e->e_attrs, ap->domain_ad );
719 1.1 christos if ( !a_dom )
720 1.1 christos dom_val = ap->default_domain;
721 1.1 christos else {
722 1.1 christos dom_val = a_dom->a_vals[0].bv_val;
723 1.1 christos }
724 1.1 christos
725 1.1 christos if ( !dom_val ) {
726 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
727 1.1 christos "user has no domain nor do we have a default, skipping\n",
728 1.1 christos op->o_log_prefix );
729 1.1 christos goto exit; /* user has no domain */
730 1.1 christos }
731 1.1 christos
732 1.1 christos realm = get_realm( dom_val, ap->mappings, ap->default_realm, &isfile );
733 1.1 christos if ( !realm ) goto exit;
734 1.1 christos
735 1.1 christos a_dn = attr_find( e->e_attrs, ap->dn_ad );
736 1.1 christos if ( !a_dn ) {
737 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
738 1.1 christos "no remote DN found on user\n",
739 1.1 christos op->o_log_prefix );
740 1.1 christos goto exit; /* user has no DN for the other directory */
741 1.1 christos }
742 1.1 christos
743 1.1 christos ber_dupbv_x( &dn, a_dn->a_vals, op->o_tmpmemctx );
744 1.1 christos be_entry_release_r( op, e );
745 1.1 christos e = NULL;
746 1.1 christos
747 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
748 1.1 christos "(realm, dn) = (%s, %s)\n",
749 1.1 christos op->o_log_prefix, realm, dn.bv_val );
750 1.1 christos
751 1.1 christos ldap_url = get_ldap_url( realm, isfile );
752 1.1 christos if ( !ldap_url ) {
753 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
754 1.1 christos "No LDAP URL obtained\n",
755 1.1 christos op->o_log_prefix );
756 1.1 christos goto exit;
757 1.1 christos }
758 1.1 christos
759 1.1 christos retry:
760 1.1 christos rc = ldap_initialize( &ld, ldap_url );
761 1.1 christos if ( rc ) {
762 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
763 1.1 christos "Cannot initialize %s: %s\n",
764 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) );
765 1.1 christos goto exit; /* user has no DN for the other directory */
766 1.1 christos }
767 1.1 christos
768 1.1 christos ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol );
769 1.1 christos
770 1.1 christos #ifdef HAVE_TLS
771 1.1 christos rc = bindconf_tls_set( &ap->ad_tls, ld );
772 1.1 christos if ( rc ) {
773 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
774 1.1 christos "bindconf_tls_set failed\n",
775 1.1 christos op->o_log_prefix );
776 1.1 christos goto exit;
777 1.1 christos }
778 1.1 christos
779 1.1 christos if ( ap->pins ) {
780 1.1 christos if ( (rc = ldap_set_option( ld, LDAP_OPT_CONNECT_CB, &ad_conncb )) !=
781 1.1 christos LDAP_SUCCESS ) {
782 1.1 christos goto exit;
783 1.1 christos }
784 1.1 christos }
785 1.1 christos
786 1.1 christos if ( (rc = ldap_connect( ld )) != LDAP_SUCCESS ) {
787 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
788 1.1 christos "Cannot connect to %s: %s\n",
789 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) );
790 1.1 christos goto exit;
791 1.1 christos }
792 1.1 christos
793 1.1 christos if ( ap->ad_tls.sb_tls && !ldap_tls_inplace( ld ) ) {
794 1.1 christos if ( (rc = ldap_start_tls_s( ld, NULL, NULL )) != LDAP_SUCCESS ) {
795 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
796 1.1 christos "LDAP TLS failed %s: %s\n",
797 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) );
798 1.1 christos goto exit;
799 1.1 christos }
800 1.1 christos }
801 1.1 christos
802 1.1 christos #endif /* HAVE_TLS */
803 1.1 christos
804 1.1 christos rc = ldap_sasl_bind_s( ld, dn.bv_val, LDAP_SASL_SIMPLE,
805 1.1 christos &op->oq_bind.rb_cred, NULL, NULL, NULL );
806 1.1 christos if ( rc == LDAP_SUCCESS ) {
807 1.1 christos if ( ap->store_on_success ) {
808 1.1 christos const char *txt;
809 1.1 christos
810 1.1 christos Operation op2 = *op;
811 1.1 christos SlapReply r2 = { REP_RESULT };
812 1.1 christos slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
813 1.1 christos Modifications m = {};
814 1.1 christos
815 1.1 christos op2.o_tag = LDAP_REQ_MODIFY;
816 1.1 christos op2.o_callback = &cb;
817 1.1 christos op2.orm_modlist = &m;
818 1.1 christos op2.orm_no_opattrs = 0;
819 1.1 christos op2.o_dn = op->o_bd->be_rootdn;
820 1.1 christos op2.o_ndn = op->o_bd->be_rootndn;
821 1.1 christos
822 1.1 christos m.sml_op = LDAP_MOD_ADD;
823 1.1 christos m.sml_flags = 0;
824 1.1 christos m.sml_next = NULL;
825 1.1 christos m.sml_type = ap->up_ad->ad_cname;
826 1.1 christos m.sml_desc = ap->up_ad;
827 1.1 christos m.sml_numvals = 1;
828 1.1 christos m.sml_values = op->o_tmpcalloc(
829 1.1 christos sizeof(struct berval), 2, op->o_tmpmemctx );
830 1.1 christos
831 1.1 christos slap_passwd_hash( &op->oq_bind.rb_cred, &m.sml_values[0], &txt );
832 1.1 christos if ( m.sml_values[0].bv_val == NULL ) {
833 1.1 christos Debug( LDAP_DEBUG_ANY, "%s remoteauth_bind: "
834 1.1 christos "password hashing for '%s' failed, storing password in "
835 1.1 christos "plain text\n",
836 1.1 christos op->o_log_prefix, op->o_req_dn.bv_val );
837 1.1 christos ber_dupbv( &m.sml_values[0], &op->oq_bind.rb_cred );
838 1.1 christos }
839 1.1 christos
840 1.1 christos /*
841 1.1 christos * If this server is a shadow use the frontend to perform this
842 1.1 christos * modify. That will trigger the update referral, which can then be
843 1.1 christos * forwarded by the chain overlay. Obviously the updateref and
844 1.1 christos * chain overlay must be configured appropriately for this to be
845 1.1 christos * useful.
846 1.1 christos */
847 1.1 christos if ( SLAP_SHADOW(op->o_bd) ) {
848 1.1 christos op2.o_bd = frontendDB;
849 1.1 christos } else {
850 1.1 christos op2.o_bd->bd_info = (BackendInfo *)on->on_info;
851 1.1 christos }
852 1.1 christos
853 1.1 christos if ( op2.o_bd->be_modify( &op2, &r2 ) != LDAP_SUCCESS ) {
854 1.1 christos Debug( LDAP_DEBUG_ANY, "%s remoteauth_bind: "
855 1.1 christos "attempt to store password in entry '%s' failed, "
856 1.1 christos "ignoring\n",
857 1.1 christos op->o_log_prefix, op->o_req_dn.bv_val );
858 1.1 christos }
859 1.1 christos ch_free( m.sml_values[0].bv_val );
860 1.1 christos }
861 1.1 christos goto exit;
862 1.1 christos }
863 1.1 christos
864 1.1 christos if ( rc == LDAP_INVALID_CREDENTIALS ) {
865 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
866 1.1 christos "ldap_sasl_bind_s (%s) failed: invalid credentials\n",
867 1.1 christos op->o_log_prefix, ldap_url );
868 1.1 christos goto exit;
869 1.1 christos }
870 1.1 christos
871 1.1 christos if ( tries < ap->retry_count ) {
872 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
873 1.1 christos "ldap_sasl_bind_s failed %s: %s (try #%d)\n",
874 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ), tries );
875 1.1 christos if ( ld ) ldap_unbind_ext_s( ld, NULL, NULL );
876 1.1 christos tries++;
877 1.1 christos goto retry;
878 1.1 christos } else
879 1.1 christos goto exit;
880 1.1 christos
881 1.1 christos exit:
882 1.1 christos if ( dn.bv_val ) {
883 1.1 christos op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
884 1.1 christos }
885 1.1 christos if ( e ) {
886 1.1 christos be_entry_release_r( op, e );
887 1.1 christos }
888 1.1 christos if ( ld ) ldap_unbind_ext_s( ld, NULL, NULL );
889 1.1 christos if ( ldap_url ) ch_free( ldap_url );
890 1.1 christos if ( realm ) ch_free( realm );
891 1.1 christos if ( rc == SLAP_CB_CONTINUE ) {
892 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
893 1.1 christos "continue\n", op->o_log_prefix );
894 1.1 christos return rc;
895 1.1 christos } else {
896 1.1 christos /* for rc == 0, frontend sends result */
897 1.1 christos if ( rc ) {
898 1.1 christos if ( rc > 0 ) {
899 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
900 1.1 christos "failed\n", op->o_log_prefix );
901 1.1 christos send_ldap_error( op, rs, rc, "remoteauth_bind failed" );
902 1.1 christos } else {
903 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: "
904 1.1 christos "operations error\n", op->o_log_prefix );
905 1.1 christos send_ldap_error( op, rs, LDAP_OPERATIONS_ERROR,
906 1.1 christos "remoteauth_bind operations error" );
907 1.1 christos }
908 1.1 christos }
909 1.1 christos
910 1.1 christos return rs->sr_err;
911 1.1 christos }
912 1.1 christos }
913 1.1 christos
914 1.1 christos static int
915 1.1 christos remoteauth_db_init( BackendDB *be, ConfigReply *cr )
916 1.1 christos {
917 1.1 christos slap_overinst *on = (slap_overinst *)be->bd_info;
918 1.1 christos ad_private *ap;
919 1.1 christos
920 1.1 christos if ( SLAP_ISGLOBALOVERLAY(be) ) {
921 1.1 christos Debug( LDAP_DEBUG_ANY, "remoteauth_db_init: "
922 1.1 christos "remoteauth overlay must be instantiated within a "
923 1.1 christos "database.\n" );
924 1.1 christos return 1;
925 1.1 christos }
926 1.1 christos
927 1.1 christos ap = ch_calloc( 1, sizeof(ad_private) );
928 1.1 christos
929 1.1 christos ap->dn = NULL;
930 1.1 christos ap->dn_ad = NULL;
931 1.1 christos ap->domain_attr = NULL;
932 1.1 christos ap->domain_ad = NULL;
933 1.1 christos
934 1.1 christos ap->up_ad = NULL;
935 1.1 christos ap->mappings = NULL;
936 1.1 christos
937 1.1 christos ap->default_realm = NULL;
938 1.1 christos ap->default_domain = NULL;
939 1.1 christos
940 1.1 christos ap->pins = NULL;
941 1.1 christos
942 1.1 christos ap->up_set = 0;
943 1.1 christos ap->retry_count = 3;
944 1.1 christos
945 1.1 christos on->on_bi.bi_private = ap;
946 1.1 christos
947 1.1 christos return LDAP_SUCCESS;
948 1.1 christos }
949 1.1 christos
950 1.1 christos static int
951 1.1 christos remoteauth_db_destroy( BackendDB *be, ConfigReply *cr )
952 1.1 christos {
953 1.1 christos slap_overinst *on = (slap_overinst *)be->bd_info;
954 1.1 christos ad_private *ap = (ad_private *)on->on_bi.bi_private;
955 1.1 christos ad_info *ai = ap->mappings;
956 1.1 christos
957 1.1 christos while ( ai ) {
958 1.1 christos if ( ai->domain ) ch_free( ai->domain );
959 1.1 christos if ( ai->realm ) ch_free( ai->realm );
960 1.1 christos ai = ai->next;
961 1.1 christos }
962 1.1 christos
963 1.1 christos if ( ap->dn ) ch_free( ap->dn );
964 1.1 christos if ( ap->default_domain ) ch_free( ap->default_domain );
965 1.1 christos if ( ap->default_realm ) ch_free( ap->default_realm );
966 1.1 christos
967 1.1 christos bindconf_free( &ap->ad_tls );
968 1.1 christos
969 1.1 christos ch_free( ap );
970 1.1 christos
971 1.1 christos return 0;
972 1.1 christos }
973 1.1 christos
974 1.1 christos static slap_overinst remoteauth;
975 1.1 christos
976 1.1 christos int
977 1.1 christos remoteauth_initialize( void )
978 1.1 christos {
979 1.1 christos int rc;
980 1.1 christos
981 1.1 christos remoteauth.on_bi.bi_type = "remoteauth";
982 1.1 christos remoteauth.on_bi.bi_flags = SLAPO_BFLAG_SINGLE;
983 1.1 christos
984 1.1 christos remoteauth.on_bi.bi_cf_ocs = remoteauthocs;
985 1.1 christos rc = config_register_schema( remoteauthcfg, remoteauthocs );
986 1.1 christos if ( rc ) return rc;
987 1.1 christos
988 1.1 christos remoteauth.on_bi.bi_db_init = remoteauth_db_init;
989 1.1 christos remoteauth.on_bi.bi_db_destroy = remoteauth_db_destroy;
990 1.1 christos remoteauth.on_bi.bi_op_bind = remoteauth_bind;
991 1.1 christos
992 1.1 christos return overlay_register( &remoteauth );
993 1.1 christos }
994 1.1 christos
995 1.1 christos #if SLAPD_OVER_ACCESSLOG == SLAPD_MOD_DYNAMIC
996 1.1 christos int
997 1.1 christos init_module( int argc, char *argv[] )
998 1.1 christos {
999 1.1 christos return remoteauth_initialize();
1000 1.1 christos }
1001 1.1 christos #endif
1002