1 1.1 christos /* $NetBSD: remoteauth.c,v 1.3 2025/09/05 21:16:32 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.3 christos * Copyright 2004-2024 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.3 2025/09/05 21:16:32 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.3 christos ber_str2bv( str, 0, 0, &bv ); 213 1.3 christos rc = value_add_one( &c->rvalue_vals, &bv ); 214 1.3 christos if ( !rc ) 215 1.3 christos rc = value_add_one( &c->rvalue_nvals, &bv ); 216 1.1 christos ch_free( str ); 217 1.3 christos if ( rc ) break; 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.3 christos ber_str2bv( ad->default_domain, 0, 0, &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.3 christos ber_str2bv( ad->default_realm, 0, 0, &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.3 christos ch_free( bv.bv_val ); 255 1.1 christos break; 256 1.1 christos case REMOTE_AUTH_TLS_PIN: { 257 1.1 christos ad_pin *pin = ad->pins; 258 1.1 christos for ( pin = ad->pins; pin; pin = pin->next ) { 259 1.1 christos bv.bv_val = ch_malloc( strlen( pin->hostname ) + 260 1.1 christos strlen( pin->pin ) + 2 ); 261 1.1 christos bv.bv_len = sprintf( 262 1.1 christos bv.bv_val, "%s %s", pin->hostname, pin->pin ); 263 1.1 christos rc = value_add_one( &c->rvalue_vals, &bv ); 264 1.1 christos if ( rc ) return rc; 265 1.1 christos rc = value_add_one( &c->rvalue_nvals, &bv ); 266 1.1 christos if ( rc ) return rc; 267 1.1 christos } 268 1.1 christos } break; 269 1.1 christos 270 1.1 christos default: 271 1.1 christos abort(); 272 1.1 christos } 273 1.1 christos break; 274 1.1 christos case LDAP_MOD_DELETE: 275 1.1 christos switch ( c->type ) { 276 1.1 christos case REMOTE_AUTH_MAPPING: 277 1.1 christos if ( c->valx < 0 ) { 278 1.1 christos /* delete all mappings */ 279 1.1 christos while ( ad->mappings ) { 280 1.1 christos map = ad->mappings; 281 1.1 christos ad->mappings = ad->mappings->next; 282 1.1 christos ch_free( map->domain ); 283 1.1 christos ch_free( map->realm ); 284 1.1 christos ch_free( map ); 285 1.1 christos } 286 1.1 christos } else { 287 1.1 christos /* delete a specific mapping indicated by 'valx'*/ 288 1.1 christos ad_info *pmap = NULL; 289 1.1 christos 290 1.1 christos for ( map = ad->mappings, i = 0; 291 1.1 christos ( map ) && ( i < c->valx ); 292 1.1 christos pmap = map, map = map->next, i++ ) 293 1.1 christos ; 294 1.1 christos 295 1.1 christos if ( pmap ) { 296 1.1 christos pmap->next = map->next; 297 1.1 christos map->next = NULL; 298 1.1 christos 299 1.1 christos ch_free( map->domain ); 300 1.1 christos ch_free( map->realm ); 301 1.1 christos ch_free( map ); 302 1.1 christos } else if ( ad->mappings ) { 303 1.1 christos /* delete the first item in the list */ 304 1.1 christos map = ad->mappings; 305 1.1 christos ad->mappings = map->next; 306 1.1 christos ch_free( map->domain ); 307 1.1 christos ch_free( map->realm ); 308 1.1 christos ch_free( map ); 309 1.1 christos } 310 1.1 christos } 311 1.1 christos break; 312 1.1 christos case REMOTE_AUTH_DN_ATTRIBUTE: 313 1.1 christos if ( ad->dn ) { 314 1.1 christos ch_free( ad->dn ); 315 1.1 christos ad->dn = NULL; /* Don't free AttributeDescription */ 316 1.1 christos } 317 1.1 christos break; 318 1.1 christos case REMOTE_AUTH_DOMAIN_ATTRIBUTE: 319 1.1 christos if ( ad->domain_attr ) { 320 1.1 christos ch_free( ad->domain_attr ); 321 1.1 christos /* Don't free AttributeDescription */ 322 1.1 christos ad->domain_attr = NULL; 323 1.1 christos } 324 1.1 christos break; 325 1.1 christos case REMOTE_AUTH_DEFAULT_DOMAIN: 326 1.1 christos if ( ad->default_domain ) { 327 1.1 christos ch_free( ad->default_domain ); 328 1.1 christos ad->default_domain = NULL; 329 1.1 christos } 330 1.1 christos break; 331 1.1 christos case REMOTE_AUTH_DEFAULT_REALM: 332 1.1 christos if ( ad->default_realm ) { 333 1.1 christos ch_free( ad->default_realm ); 334 1.1 christos ad->default_realm = NULL; 335 1.1 christos } 336 1.1 christos break; 337 1.1 christos case REMOTE_AUTH_TLS: 338 1.1 christos /* MUST + SINGLE-VALUE -> this is a replace */ 339 1.1 christos bindconf_free( &ad->ad_tls ); 340 1.1 christos break; 341 1.1 christos case REMOTE_AUTH_TLS_PIN: 342 1.1 christos while ( ad->pins ) { 343 1.1 christos ad_pin *pin = ad->pins; 344 1.1 christos ad->pins = ad->pins->next; 345 1.1 christos ch_free( pin->hostname ); 346 1.1 christos ch_free( pin->pin ); 347 1.1 christos ch_free( pin ); 348 1.1 christos } 349 1.1 christos break; 350 1.1 christos /* ARG_OFFSET */ 351 1.1 christos case REMOTE_AUTH_STORE_ON_SUCCESS: 352 1.1 christos case REMOTE_AUTH_RETRY_COUNT: 353 1.1 christos abort(); 354 1.1 christos break; 355 1.1 christos default: 356 1.1 christos abort(); 357 1.1 christos } 358 1.1 christos break; 359 1.1 christos case SLAP_CONFIG_ADD: 360 1.1 christos case LDAP_MOD_ADD: 361 1.1 christos switch ( c->type ) { 362 1.1 christos case REMOTE_AUTH_MAPPING: 363 1.1 christos /* add mapping to head of list */ 364 1.1 christos map = ch_malloc( sizeof(ad_info) ); 365 1.1 christos map->domain = ber_strdup( c->argv[1] ); 366 1.1 christos map->realm = ber_strdup( c->argv[2] ); 367 1.1 christos map->next = ad->mappings; 368 1.1 christos ad->mappings = map; 369 1.1 christos 370 1.1 christos break; 371 1.1 christos case REMOTE_AUTH_DN_ATTRIBUTE: 372 1.1 christos if ( slap_str2ad( c->argv[1], &ad->dn_ad, &text ) == 373 1.1 christos LDAP_SUCCESS ) { 374 1.1 christos ad->dn = ber_strdup( ad->dn_ad->ad_cname.bv_val ); 375 1.1 christos } else { 376 1.1 christos strncpy( c->cr_msg, text, sizeof(c->cr_msg) ); 377 1.1 christos c->cr_msg[sizeof(c->cr_msg) - 1] = '\0'; 378 1.1 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 379 1.1 christos rc = ARG_BAD_CONF; 380 1.1 christos } 381 1.1 christos break; 382 1.1 christos case REMOTE_AUTH_DOMAIN_ATTRIBUTE: 383 1.1 christos if ( slap_str2ad( c->argv[1], &ad->domain_ad, &text ) == 384 1.1 christos LDAP_SUCCESS ) { 385 1.1 christos ad->domain_attr = 386 1.1 christos ber_strdup( ad->domain_ad->ad_cname.bv_val ); 387 1.1 christos } else { 388 1.1 christos strncpy( c->cr_msg, text, sizeof(c->cr_msg) ); 389 1.1 christos c->cr_msg[sizeof(c->cr_msg) - 1] = '\0'; 390 1.1 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 391 1.1 christos rc = ARG_BAD_CONF; 392 1.1 christos } 393 1.1 christos break; 394 1.1 christos case REMOTE_AUTH_DEFAULT_DOMAIN: 395 1.1 christos if ( ad->default_domain ) { 396 1.1 christos ch_free( ad->default_domain ); 397 1.1 christos ad->default_domain = NULL; 398 1.1 christos } 399 1.1 christos ad->default_domain = ber_strdup( c->argv[1] ); 400 1.1 christos break; 401 1.1 christos case REMOTE_AUTH_DEFAULT_REALM: 402 1.1 christos if ( ad->default_realm ) { 403 1.1 christos ch_free( ad->default_realm ); 404 1.1 christos ad->default_realm = NULL; 405 1.1 christos } 406 1.1 christos ad->default_realm = ber_strdup( c->argv[1] ); 407 1.1 christos break; 408 1.1 christos case REMOTE_AUTH_TLS: 409 1.1 christos for ( i=1; i < c->argc; i++ ) { 410 1.1 christos if ( bindconf_tls_parse( c->argv[i], &ad->ad_tls ) ) { 411 1.1 christos rc = 1; 412 1.1 christos break; 413 1.1 christos } 414 1.1 christos } 415 1.1 christos bindconf_tls_defaults( &ad->ad_tls ); 416 1.1 christos break; 417 1.1 christos case REMOTE_AUTH_TLS_PIN: { 418 1.1 christos ad_pin *pin = ch_calloc( 1, sizeof(ad_pin) ); 419 1.1 christos 420 1.1 christos pin->hostname = ber_strdup( c->argv[1] ); 421 1.1 christos pin->pin = ber_strdup( c->argv[2] ); 422 1.1 christos pin->next = ad->pins; 423 1.1 christos ad->pins = pin; 424 1.1 christos } break; 425 1.1 christos /* ARG_OFFSET */ 426 1.1 christos case REMOTE_AUTH_STORE_ON_SUCCESS: 427 1.1 christos case REMOTE_AUTH_RETRY_COUNT: 428 1.1 christos abort(); 429 1.1 christos break; 430 1.1 christos default: 431 1.1 christos abort(); 432 1.1 christos } 433 1.1 christos break; 434 1.1 christos default: 435 1.1 christos abort(); 436 1.1 christos } 437 1.1 christos 438 1.1 christos return rc; 439 1.1 christos } 440 1.1 christos 441 1.1 christos static char * 442 1.1 christos get_realm( 443 1.1 christos const char *domain, 444 1.1 christos ad_info *mappings, 445 1.1 christos const char *default_realm, 446 1.1 christos int *isfile ) 447 1.1 christos { 448 1.1 christos ad_info *ai; 449 1.1 christos char *dom = NULL, *ch, *ret = NULL; 450 1.1 christos 451 1.1 christos if ( isfile ) *isfile = 0; 452 1.1 christos 453 1.1 christos if ( !domain ) { 454 1.1 christos ret = default_realm ? ch_strdup( default_realm ) : NULL; 455 1.1 christos goto exit; 456 1.1 christos } 457 1.1 christos 458 1.1 christos /* munge any DOMAIN\user or DOMAIN:user values into just DOMAIN */ 459 1.1 christos 460 1.1 christos ch = strchr( domain, '\\' ); 461 1.1 christos if ( !ch ) ch = strchr( domain, ':' ); 462 1.1 christos 463 1.1 christos if ( ch ) { 464 1.1 christos dom = ch_malloc( ch - domain + 1 ); 465 1.1 christos strncpy( dom, domain, ch - domain ); 466 1.1 christos dom[ch - domain] = '\0'; 467 1.1 christos } else { 468 1.1 christos dom = ch_strdup( domain ); 469 1.1 christos } 470 1.1 christos 471 1.1 christos for ( ai = mappings; ai; ai = ai->next ) 472 1.1 christos if ( strcasecmp( ai->domain, dom ) == 0 ) { 473 1.1 christos ret = ch_strdup( ai->realm ); 474 1.1 christos break; 475 1.1 christos } 476 1.1 christos 477 1.1 christos if ( !ai ) 478 1.1 christos ret = default_realm ? ch_strdup( default_realm ) : 479 1.1 christos NULL; /* no mapping found */ 480 1.1 christos exit: 481 1.1 christos if ( dom ) ch_free( dom ); 482 1.1 christos if ( ret && 483 1.1 christos ( strncasecmp( ret, FILE_PREFIX, strlen( FILE_PREFIX ) ) == 0 ) ) { 484 1.1 christos char *p; 485 1.1 christos 486 1.1 christos p = ret; 487 1.1 christos ret = ch_strdup( p + strlen( FILE_PREFIX ) ); 488 1.1 christos ch_free( p ); 489 1.1 christos if ( isfile ) *isfile = 1; 490 1.1 christos } 491 1.1 christos 492 1.1 christos return ret; 493 1.1 christos } 494 1.1 christos 495 1.1 christos static char * 496 1.1 christos get_ldap_url( const char *realm, int isfile ) 497 1.1 christos { 498 1.1 christos char *ldap_url = NULL; 499 1.1 christos FILE *fp; 500 1.1 christos 501 1.1 christos if ( !realm ) return NULL; 502 1.1 christos 503 1.1 christos if ( !isfile ) { 504 1.1 christos if ( strstr( realm, "://" ) ) { 505 1.1 christos return ch_strdup( realm ); 506 1.1 christos } 507 1.1 christos 508 1.1 christos ldap_url = ch_malloc( 1 + strlen( LDAP_PREFIX ) + strlen( realm ) ); 509 1.1 christos sprintf( ldap_url, "%s%s", LDAP_PREFIX, realm ); 510 1.1 christos return ldap_url; 511 1.1 christos } 512 1.1 christos 513 1.1 christos fp = fopen( realm, "r" ); 514 1.1 christos if ( !fp ) { 515 1.1 christos char ebuf[128]; 516 1.1 christos int saved_errno = errno; 517 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth: " 518 1.1 christos "Unable to open realm file (%s)\n", 519 1.1 christos sock_errstr( saved_errno, ebuf, sizeof(ebuf) ) ); 520 1.1 christos return NULL; 521 1.1 christos } 522 1.1 christos /* 523 1.1 christos * Read each line in the file and return a URL of the form 524 1.1 christos * "ldap://<line1> ldap://<line2> ... ldap://<lineN>" 525 1.1 christos * which can be passed to ldap_initialize. 526 1.1 christos */ 527 1.1 christos while ( !feof( fp ) ) { 528 1.1 christos char line[512], *p; 529 1.1 christos 530 1.1 christos p = fgets( line, sizeof(line), fp ); 531 1.1 christos if ( !p ) continue; 532 1.1 christos 533 1.1 christos /* terminate line at first whitespace */ 534 1.1 christos for ( p = line; *p; p++ ) 535 1.1 christos if ( isspace( *p ) ) { 536 1.1 christos *p = '\0'; 537 1.1 christos break; 538 1.1 christos } 539 1.1 christos 540 1.1 christos if ( ldap_url ) { 541 1.1 christos char *nu; 542 1.1 christos 543 1.1 christos nu = ch_malloc( strlen( ldap_url ) + 2 + strlen( LDAP_PREFIX ) + 544 1.1 christos strlen( line ) ); 545 1.1 christos 546 1.1 christos if ( strstr( line, "://" ) ) { 547 1.1 christos sprintf( nu, "%s %s", ldap_url, line ); 548 1.1 christos } else { 549 1.1 christos sprintf( nu, "%s %s%s", ldap_url, LDAP_PREFIX, line ); 550 1.1 christos } 551 1.1 christos ch_free( ldap_url ); 552 1.1 christos ldap_url = nu; 553 1.1 christos } else { 554 1.1 christos ldap_url = ch_malloc( 1 + strlen( line ) + strlen( LDAP_PREFIX ) ); 555 1.1 christos if ( strstr( line, "://" ) ) { 556 1.1 christos strcpy( ldap_url, line ); 557 1.1 christos } else { 558 1.1 christos sprintf( ldap_url, "%s%s", LDAP_PREFIX, line ); 559 1.1 christos } 560 1.1 christos } 561 1.1 christos } 562 1.1 christos 563 1.1 christos fclose( fp ); 564 1.1 christos 565 1.1 christos return ldap_url; 566 1.1 christos } 567 1.1 christos 568 1.1 christos static void 569 1.1 christos trace_remoteauth_parameters( ad_private *ap ) 570 1.1 christos { 571 1.1 christos ad_info *pad_info; 572 1.1 christos struct berval bv; 573 1.1 christos 574 1.1 christos if ( !ap ) return; 575 1.1 christos 576 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_dn_attribute: %s\n", 577 1.1 christos ap->dn ? ap->dn : "NULL" ); 578 1.1 christos 579 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_domain_attribute: %s\n", 580 1.1 christos ap->domain_attr ? ap->domain_attr : "NULL" ); 581 1.1 christos 582 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_default_realm: %s\n", 583 1.1 christos ap->default_realm ? ap->default_realm : "NULL" ); 584 1.1 christos 585 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_default_domain: %s\n", 586 1.1 christos ap->default_domain ? ap->default_domain : "NULL" ); 587 1.1 christos 588 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_retry_count: %d\n", ap->retry_count ); 589 1.1 christos 590 1.1 christos bindconf_tls_unparse( &ap->ad_tls, &bv ); 591 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_tls:%s\n", bv.bv_val ); 592 1.1 christos ch_free( bv.bv_val ); 593 1.1 christos 594 1.1 christos pad_info = ap->mappings; 595 1.1 christos while ( pad_info ) { 596 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_mappings(%s,%s)\n", 597 1.1 christos pad_info->domain ? pad_info->domain : "NULL", 598 1.1 christos pad_info->realm ? pad_info->realm : "NULL" ); 599 1.1 christos pad_info = pad_info->next; 600 1.1 christos } 601 1.1 christos 602 1.1 christos return; 603 1.1 christos } 604 1.1 christos 605 1.1 christos static int 606 1.1 christos remoteauth_conn_cb( 607 1.1 christos LDAP *ld, 608 1.1 christos Sockbuf *sb, 609 1.1 christos LDAPURLDesc *srv, 610 1.1 christos struct sockaddr *addr, 611 1.1 christos struct ldap_conncb *ctx ) 612 1.1 christos { 613 1.1 christos ad_private *ap = ctx->lc_arg; 614 1.1 christos ad_pin *pin = NULL; 615 1.1 christos char *host; 616 1.1 christos 617 1.1 christos host = srv->lud_host; 618 1.1 christos if ( !host || !*host ) { 619 1.1 christos host = "localhost"; 620 1.1 christos } 621 1.1 christos 622 1.1 christos for ( pin = ap->pins; pin; pin = pin->next ) { 623 1.1 christos if ( !strcasecmp( host, pin->hostname ) ) break; 624 1.1 christos } 625 1.1 christos 626 1.1 christos if ( pin ) { 627 1.1 christos int rc = ldap_set_option( ld, LDAP_OPT_X_TLS_PEERKEY_HASH, pin->pin ); 628 1.1 christos if ( rc == LDAP_SUCCESS ) { 629 1.1 christos return 0; 630 1.1 christos } 631 1.1 christos 632 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_conn_cb: " 633 1.1 christos "TLS Peerkey hash could not be set to '%s': %d\n", 634 1.1 christos pin->pin, rc ); 635 1.1 christos } else { 636 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_conn_cb: " 637 1.1 christos "No TLS Peerkey hash found for host '%s'\n", 638 1.1 christos host ); 639 1.1 christos } 640 1.1 christos 641 1.1 christos return -1; 642 1.1 christos } 643 1.1 christos 644 1.1 christos static void 645 1.1 christos remoteauth_conn_delcb( LDAP *ld, Sockbuf *sb, struct ldap_conncb *ctx ) 646 1.1 christos { 647 1.1 christos return; 648 1.1 christos } 649 1.1 christos 650 1.1 christos static int 651 1.1 christos remoteauth_bind( Operation *op, SlapReply *rs ) 652 1.1 christos { 653 1.1 christos Entry *e; 654 1.1 christos int rc; 655 1.1 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 656 1.1 christos ad_private *ap = (ad_private *)on->on_bi.bi_private; 657 1.1 christos Attribute *a_dom, *a_dn; 658 1.1 christos struct ldap_conncb ad_conncb = { .lc_add = remoteauth_conn_cb, 659 1.1 christos .lc_del = remoteauth_conn_delcb, 660 1.1 christos .lc_arg = ap }; 661 1.1 christos struct berval dn = { 0 }; 662 1.1 christos char *dom_val, *realm = NULL; 663 1.1 christos char *ldap_url = NULL; 664 1.1 christos LDAP *ld = NULL; 665 1.1 christos int protocol = LDAP_VERSION3, isfile = 0; 666 1.1 christos int tries = 0; 667 1.1 christos 668 1.1 christos if ( LogTest( LDAP_DEBUG_TRACE ) ) { 669 1.1 christos trace_remoteauth_parameters( ap ); 670 1.1 christos } 671 1.1 christos 672 1.1 christos if ( op->orb_method != LDAP_AUTH_SIMPLE ) 673 1.1 christos return SLAP_CB_CONTINUE; /* only do password auth */ 674 1.1 christos 675 1.1 christos /* Can't handle root via this mechanism */ 676 1.1 christos if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) return SLAP_CB_CONTINUE; 677 1.1 christos 678 1.1 christos if ( !ap->up_set ) { 679 1.1 christos const char *txt = NULL; 680 1.1 christos 681 1.1 christos if ( slap_str2ad( UP_STR, &ap->up_ad, &txt ) ) 682 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: " 683 1.1 christos "userPassword attr undefined: %s\n", 684 1.1 christos txt ? txt : "" ); 685 1.1 christos ap->up_set = 1; 686 1.1 christos } 687 1.1 christos 688 1.1 christos if ( !ap->up_ad ) { 689 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: " 690 1.1 christos "password attribute not configured\n" ); 691 1.1 christos return SLAP_CB_CONTINUE; /* userPassword not defined */ 692 1.1 christos } 693 1.1 christos 694 1.1 christos if ( !ap->dn ) { 695 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: " 696 1.1 christos "remote DN attribute not configured\n" ); 697 1.1 christos return SLAP_CB_CONTINUE; /* no mapped DN attribute */ 698 1.1 christos } 699 1.1 christos 700 1.1 christos if ( !ap->domain_attr ) { 701 1.1 christos Debug( LDAP_DEBUG_TRACE, "remoteauth_bind: " 702 1.1 christos "domain attribute not configured\n" ); 703 1.1 christos return SLAP_CB_CONTINUE; /* no way to know domain */ 704 1.1 christos } 705 1.1 christos 706 1.1 christos op->o_bd->bd_info = (BackendInfo *)on->on_info; 707 1.1 christos rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); 708 1.1 christos if ( rc != LDAP_SUCCESS ) return SLAP_CB_CONTINUE; 709 1.1 christos 710 1.1 christos rc = SLAP_CB_CONTINUE; 711 1.1 christos /* if userPassword is defined in entry, skip to the end */ 712 1.1 christos if ( attr_find( e->e_attrs, ap->up_ad ) ) { 713 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 714 1.1 christos "user has a password, skipping\n", 715 1.1 christos op->o_log_prefix ); 716 1.1 christos goto exit; 717 1.1 christos } 718 1.1 christos 719 1.1 christos a_dom = attr_find( e->e_attrs, ap->domain_ad ); 720 1.1 christos if ( !a_dom ) 721 1.1 christos dom_val = ap->default_domain; 722 1.1 christos else { 723 1.1 christos dom_val = a_dom->a_vals[0].bv_val; 724 1.1 christos } 725 1.1 christos 726 1.1 christos if ( !dom_val ) { 727 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 728 1.1 christos "user has no domain nor do we have a default, skipping\n", 729 1.1 christos op->o_log_prefix ); 730 1.1 christos goto exit; /* user has no domain */ 731 1.1 christos } 732 1.1 christos 733 1.1 christos realm = get_realm( dom_val, ap->mappings, ap->default_realm, &isfile ); 734 1.1 christos if ( !realm ) goto exit; 735 1.1 christos 736 1.1 christos a_dn = attr_find( e->e_attrs, ap->dn_ad ); 737 1.1 christos if ( !a_dn ) { 738 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 739 1.1 christos "no remote DN found on user\n", 740 1.1 christos op->o_log_prefix ); 741 1.1 christos goto exit; /* user has no DN for the other directory */ 742 1.1 christos } 743 1.1 christos 744 1.1 christos ber_dupbv_x( &dn, a_dn->a_vals, op->o_tmpmemctx ); 745 1.1 christos be_entry_release_r( op, e ); 746 1.1 christos e = NULL; 747 1.1 christos 748 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 749 1.1 christos "(realm, dn) = (%s, %s)\n", 750 1.1 christos op->o_log_prefix, realm, dn.bv_val ); 751 1.1 christos 752 1.1 christos ldap_url = get_ldap_url( realm, isfile ); 753 1.1 christos if ( !ldap_url ) { 754 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 755 1.1 christos "No LDAP URL obtained\n", 756 1.1 christos op->o_log_prefix ); 757 1.1 christos goto exit; 758 1.1 christos } 759 1.1 christos 760 1.1 christos retry: 761 1.1 christos rc = ldap_initialize( &ld, ldap_url ); 762 1.1 christos if ( rc ) { 763 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 764 1.1 christos "Cannot initialize %s: %s\n", 765 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) ); 766 1.1 christos goto exit; /* user has no DN for the other directory */ 767 1.1 christos } 768 1.1 christos 769 1.1 christos ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ); 770 1.1 christos 771 1.1 christos #ifdef HAVE_TLS 772 1.1 christos rc = bindconf_tls_set( &ap->ad_tls, ld ); 773 1.1 christos if ( rc ) { 774 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 775 1.1 christos "bindconf_tls_set failed\n", 776 1.1 christos op->o_log_prefix ); 777 1.1 christos goto exit; 778 1.1 christos } 779 1.1 christos 780 1.1 christos if ( ap->pins ) { 781 1.1 christos if ( (rc = ldap_set_option( ld, LDAP_OPT_CONNECT_CB, &ad_conncb )) != 782 1.1 christos LDAP_SUCCESS ) { 783 1.1 christos goto exit; 784 1.1 christos } 785 1.1 christos } 786 1.1 christos 787 1.1 christos if ( (rc = ldap_connect( ld )) != LDAP_SUCCESS ) { 788 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 789 1.1 christos "Cannot connect to %s: %s\n", 790 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) ); 791 1.1 christos goto exit; 792 1.1 christos } 793 1.1 christos 794 1.1 christos if ( ap->ad_tls.sb_tls && !ldap_tls_inplace( ld ) ) { 795 1.1 christos if ( (rc = ldap_start_tls_s( ld, NULL, NULL )) != LDAP_SUCCESS ) { 796 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 797 1.1 christos "LDAP TLS failed %s: %s\n", 798 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ) ); 799 1.1 christos goto exit; 800 1.1 christos } 801 1.1 christos } 802 1.1 christos 803 1.1 christos #endif /* HAVE_TLS */ 804 1.1 christos 805 1.1 christos rc = ldap_sasl_bind_s( ld, dn.bv_val, LDAP_SASL_SIMPLE, 806 1.1 christos &op->oq_bind.rb_cred, NULL, NULL, NULL ); 807 1.1 christos if ( rc == LDAP_SUCCESS ) { 808 1.1 christos if ( ap->store_on_success ) { 809 1.1 christos const char *txt; 810 1.1 christos 811 1.1 christos Operation op2 = *op; 812 1.1 christos SlapReply r2 = { REP_RESULT }; 813 1.1 christos slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; 814 1.1 christos Modifications m = {}; 815 1.1 christos 816 1.1 christos op2.o_tag = LDAP_REQ_MODIFY; 817 1.1 christos op2.o_callback = &cb; 818 1.1 christos op2.orm_modlist = &m; 819 1.1 christos op2.orm_no_opattrs = 0; 820 1.1 christos op2.o_dn = op->o_bd->be_rootdn; 821 1.1 christos op2.o_ndn = op->o_bd->be_rootndn; 822 1.1 christos 823 1.1 christos m.sml_op = LDAP_MOD_ADD; 824 1.1 christos m.sml_flags = 0; 825 1.1 christos m.sml_next = NULL; 826 1.1 christos m.sml_type = ap->up_ad->ad_cname; 827 1.1 christos m.sml_desc = ap->up_ad; 828 1.1 christos m.sml_numvals = 1; 829 1.1 christos m.sml_values = op->o_tmpcalloc( 830 1.1 christos sizeof(struct berval), 2, op->o_tmpmemctx ); 831 1.1 christos 832 1.1 christos slap_passwd_hash( &op->oq_bind.rb_cred, &m.sml_values[0], &txt ); 833 1.1 christos if ( m.sml_values[0].bv_val == NULL ) { 834 1.1 christos Debug( LDAP_DEBUG_ANY, "%s remoteauth_bind: " 835 1.1 christos "password hashing for '%s' failed, storing password in " 836 1.1 christos "plain text\n", 837 1.1 christos op->o_log_prefix, op->o_req_dn.bv_val ); 838 1.1 christos ber_dupbv( &m.sml_values[0], &op->oq_bind.rb_cred ); 839 1.1 christos } 840 1.1 christos 841 1.1 christos /* 842 1.1 christos * If this server is a shadow use the frontend to perform this 843 1.1 christos * modify. That will trigger the update referral, which can then be 844 1.1 christos * forwarded by the chain overlay. Obviously the updateref and 845 1.1 christos * chain overlay must be configured appropriately for this to be 846 1.1 christos * useful. 847 1.1 christos */ 848 1.1 christos if ( SLAP_SHADOW(op->o_bd) ) { 849 1.1 christos op2.o_bd = frontendDB; 850 1.1 christos } else { 851 1.1 christos op2.o_bd->bd_info = (BackendInfo *)on->on_info; 852 1.1 christos } 853 1.1 christos 854 1.1 christos if ( op2.o_bd->be_modify( &op2, &r2 ) != LDAP_SUCCESS ) { 855 1.1 christos Debug( LDAP_DEBUG_ANY, "%s remoteauth_bind: " 856 1.1 christos "attempt to store password in entry '%s' failed, " 857 1.1 christos "ignoring\n", 858 1.1 christos op->o_log_prefix, op->o_req_dn.bv_val ); 859 1.1 christos } 860 1.1 christos ch_free( m.sml_values[0].bv_val ); 861 1.1 christos } 862 1.1 christos goto exit; 863 1.1 christos } 864 1.1 christos 865 1.1 christos if ( rc == LDAP_INVALID_CREDENTIALS ) { 866 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 867 1.1 christos "ldap_sasl_bind_s (%s) failed: invalid credentials\n", 868 1.1 christos op->o_log_prefix, ldap_url ); 869 1.1 christos goto exit; 870 1.1 christos } 871 1.1 christos 872 1.1 christos if ( tries < ap->retry_count ) { 873 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 874 1.1 christos "ldap_sasl_bind_s failed %s: %s (try #%d)\n", 875 1.1 christos op->o_log_prefix, ldap_url, ldap_err2string( rc ), tries ); 876 1.1 christos if ( ld ) ldap_unbind_ext_s( ld, NULL, NULL ); 877 1.1 christos tries++; 878 1.1 christos goto retry; 879 1.1 christos } else 880 1.1 christos goto exit; 881 1.1 christos 882 1.1 christos exit: 883 1.1 christos if ( dn.bv_val ) { 884 1.1 christos op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); 885 1.1 christos } 886 1.1 christos if ( e ) { 887 1.1 christos be_entry_release_r( op, e ); 888 1.1 christos } 889 1.1 christos if ( ld ) ldap_unbind_ext_s( ld, NULL, NULL ); 890 1.1 christos if ( ldap_url ) ch_free( ldap_url ); 891 1.1 christos if ( realm ) ch_free( realm ); 892 1.1 christos if ( rc == SLAP_CB_CONTINUE ) { 893 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 894 1.1 christos "continue\n", op->o_log_prefix ); 895 1.1 christos return rc; 896 1.1 christos } else { 897 1.1 christos /* for rc == 0, frontend sends result */ 898 1.1 christos if ( rc ) { 899 1.1 christos if ( rc > 0 ) { 900 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 901 1.1 christos "failed\n", op->o_log_prefix ); 902 1.1 christos send_ldap_error( op, rs, rc, "remoteauth_bind failed" ); 903 1.1 christos } else { 904 1.1 christos Debug( LDAP_DEBUG_TRACE, "%s remoteauth_bind: " 905 1.1 christos "operations error\n", op->o_log_prefix ); 906 1.1 christos send_ldap_error( op, rs, LDAP_OPERATIONS_ERROR, 907 1.1 christos "remoteauth_bind operations error" ); 908 1.1 christos } 909 1.1 christos } 910 1.1 christos 911 1.1 christos return rs->sr_err; 912 1.1 christos } 913 1.1 christos } 914 1.1 christos 915 1.1 christos static int 916 1.1 christos remoteauth_db_init( BackendDB *be, ConfigReply *cr ) 917 1.1 christos { 918 1.1 christos slap_overinst *on = (slap_overinst *)be->bd_info; 919 1.1 christos ad_private *ap; 920 1.1 christos 921 1.1 christos if ( SLAP_ISGLOBALOVERLAY(be) ) { 922 1.1 christos Debug( LDAP_DEBUG_ANY, "remoteauth_db_init: " 923 1.1 christos "remoteauth overlay must be instantiated within a " 924 1.1 christos "database.\n" ); 925 1.1 christos return 1; 926 1.1 christos } 927 1.1 christos 928 1.1 christos ap = ch_calloc( 1, sizeof(ad_private) ); 929 1.1 christos 930 1.1 christos ap->dn = NULL; 931 1.1 christos ap->dn_ad = NULL; 932 1.1 christos ap->domain_attr = NULL; 933 1.1 christos ap->domain_ad = NULL; 934 1.1 christos 935 1.1 christos ap->up_ad = NULL; 936 1.1 christos ap->mappings = NULL; 937 1.1 christos 938 1.1 christos ap->default_realm = NULL; 939 1.1 christos ap->default_domain = NULL; 940 1.1 christos 941 1.1 christos ap->pins = NULL; 942 1.1 christos 943 1.1 christos ap->up_set = 0; 944 1.1 christos ap->retry_count = 3; 945 1.1 christos 946 1.1 christos on->on_bi.bi_private = ap; 947 1.1 christos 948 1.1 christos return LDAP_SUCCESS; 949 1.1 christos } 950 1.1 christos 951 1.1 christos static int 952 1.1 christos remoteauth_db_destroy( BackendDB *be, ConfigReply *cr ) 953 1.1 christos { 954 1.1 christos slap_overinst *on = (slap_overinst *)be->bd_info; 955 1.1 christos ad_private *ap = (ad_private *)on->on_bi.bi_private; 956 1.1 christos ad_info *ai = ap->mappings; 957 1.1 christos 958 1.1 christos while ( ai ) { 959 1.3 christos ad_info *next = ai->next; 960 1.3 christos 961 1.1 christos if ( ai->domain ) ch_free( ai->domain ); 962 1.1 christos if ( ai->realm ) ch_free( ai->realm ); 963 1.3 christos 964 1.3 christos ch_free( ai ); 965 1.3 christos ai = next; 966 1.1 christos } 967 1.1 christos 968 1.1 christos if ( ap->dn ) ch_free( ap->dn ); 969 1.1 christos if ( ap->default_domain ) ch_free( ap->default_domain ); 970 1.1 christos if ( ap->default_realm ) ch_free( ap->default_realm ); 971 1.3 christos if ( ap->domain_attr ) ch_free( ap->domain_attr ); 972 1.1 christos 973 1.1 christos bindconf_free( &ap->ad_tls ); 974 1.1 christos 975 1.1 christos ch_free( ap ); 976 1.1 christos 977 1.1 christos return 0; 978 1.1 christos } 979 1.1 christos 980 1.1 christos static slap_overinst remoteauth; 981 1.1 christos 982 1.1 christos int 983 1.1 christos remoteauth_initialize( void ) 984 1.1 christos { 985 1.1 christos int rc; 986 1.1 christos 987 1.1 christos remoteauth.on_bi.bi_type = "remoteauth"; 988 1.1 christos remoteauth.on_bi.bi_flags = SLAPO_BFLAG_SINGLE; 989 1.1 christos 990 1.1 christos remoteauth.on_bi.bi_cf_ocs = remoteauthocs; 991 1.1 christos rc = config_register_schema( remoteauthcfg, remoteauthocs ); 992 1.1 christos if ( rc ) return rc; 993 1.1 christos 994 1.1 christos remoteauth.on_bi.bi_db_init = remoteauth_db_init; 995 1.1 christos remoteauth.on_bi.bi_db_destroy = remoteauth_db_destroy; 996 1.1 christos remoteauth.on_bi.bi_op_bind = remoteauth_bind; 997 1.1 christos 998 1.1 christos return overlay_register( &remoteauth ); 999 1.1 christos } 1000 1.1 christos 1001 1.1 christos #if SLAPD_OVER_ACCESSLOG == SLAPD_MOD_DYNAMIC 1002 1.1 christos int 1003 1.1 christos init_module( int argc, char *argv[] ) 1004 1.1 christos { 1005 1.1 christos return remoteauth_initialize(); 1006 1.1 christos } 1007 1.1 christos #endif 1008