1/* $NetBSD: config.c,v 1.3 2021/08/14 16:14:59 christos Exp $ */ 2 3/* config.c - ldap backend configuration file routine */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2003-2021 The OpenLDAP Foundation. 8 * Portions Copyright 1999-2003 Howard Chu. 9 * Portions Copyright 2000-2003 Pierangelo Masarati. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted only as authorized by the OpenLDAP 14 * Public License. 15 * 16 * A copy of this license is available in the file LICENSE in the 17 * top-level directory of the distribution or, alternatively, at 18 * <http://www.OpenLDAP.org/license.html>. 19 */ 20/* ACKNOWLEDGEMENTS: 21 * This work was initially developed by the Howard Chu for inclusion 22 * in OpenLDAP Software and subsequently enhanced by Pierangelo 23 * Masarati. 24 */ 25 26#include <sys/cdefs.h> 27__RCSID("$NetBSD: config.c,v 1.3 2021/08/14 16:14:59 christos Exp $"); 28 29#include "portable.h" 30 31#include <stdio.h> 32 33#include <ac/string.h> 34#include <ac/ctype.h> 35#include <ac/socket.h> 36 37#include "slap.h" 38#include "slap-config.h" 39#include "back-ldap.h" 40#include "lutil.h" 41#include "ldif.h" 42 43static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami; 44 45static ConfigDriver ldap_back_cf_gen; 46static ConfigDriver ldap_pbind_cf_gen; 47 48enum { 49 LDAP_BACK_CFG_URI = 1, 50 LDAP_BACK_CFG_TLS, 51 LDAP_BACK_CFG_ACL_BIND, 52 LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 53 LDAP_BACK_CFG_IDASSERT_PASSTHRU, 54 LDAP_BACK_CFG_IDASSERT_BIND, 55 LDAP_BACK_CFG_REBIND, 56 LDAP_BACK_CFG_CHASE, 57 LDAP_BACK_CFG_T_F, 58 LDAP_BACK_CFG_WHOAMI, 59 LDAP_BACK_CFG_TIMEOUT, 60 LDAP_BACK_CFG_IDLE_TIMEOUT, 61 LDAP_BACK_CFG_CONN_TTL, 62 LDAP_BACK_CFG_NETWORK_TIMEOUT, 63 LDAP_BACK_CFG_VERSION, 64 LDAP_BACK_CFG_SINGLECONN, 65 LDAP_BACK_CFG_USETEMP, 66 LDAP_BACK_CFG_CONNPOOLMAX, 67 LDAP_BACK_CFG_CANCEL, 68 LDAP_BACK_CFG_QUARANTINE, 69 LDAP_BACK_CFG_ST_REQUEST, 70 LDAP_BACK_CFG_NOREFS, 71 LDAP_BACK_CFG_NOUNDEFFILTER, 72 LDAP_BACK_CFG_ONERR, 73 74 LDAP_BACK_CFG_KEEPALIVE, 75 LDAP_BACK_CFG_TCP_USER_TIMEOUT, 76 77 LDAP_BACK_CFG_OMIT_UNKNOWN_SCHEMA, 78 79 LDAP_BACK_CFG_LAST 80}; 81 82static ConfigTable ldapcfg[] = { 83 { "uri", "uri", 2, 2, 0, 84 ARG_MAGIC|LDAP_BACK_CFG_URI, 85 ldap_back_cf_gen, "( OLcfgDbAt:0.14 " 86 "NAME 'olcDbURI' " 87 "DESC 'URI (list) for remote DSA' " 88 "EQUALITY caseExactMatch " 89 "SYNTAX OMsDirectoryString " 90 "SINGLE-VALUE )", 91 NULL, NULL }, 92 { "tls", "what", 2, 0, 0, 93 ARG_MAGIC|LDAP_BACK_CFG_TLS, 94 ldap_back_cf_gen, "( OLcfgDbAt:3.1 " 95 "NAME 'olcDbStartTLS' " 96 "DESC 'StartTLS' " 97 "EQUALITY caseExactMatch " 98 "SYNTAX OMsDirectoryString " 99 "SINGLE-VALUE )", 100 NULL, NULL }, 101 { "acl-bind", "args", 2, 0, 0, 102 ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND, 103 ldap_back_cf_gen, "( OLcfgDbAt:3.4 " 104 "NAME 'olcDbACLBind' " 105 "DESC 'Remote ACL administrative identity auth bind configuration' " 106 "EQUALITY caseIgnoreMatch " 107 "SYNTAX OMsDirectoryString " 108 "SINGLE-VALUE )", 109 NULL, NULL }, 110 { "idassert-bind", "args", 2, 0, 0, 111 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND, 112 ldap_back_cf_gen, "( OLcfgDbAt:3.7 " 113 "NAME 'olcDbIDAssertBind' " 114 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' " 115 "EQUALITY caseIgnoreMatch " 116 "SYNTAX OMsDirectoryString " 117 "SINGLE-VALUE )", 118 NULL, NULL }, 119 { "idassert-authzFrom", "authzRule", 2, 2, 0, 120 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 121 ldap_back_cf_gen, "( OLcfgDbAt:3.9 " 122 "NAME 'olcDbIDAssertAuthzFrom' " 123 "DESC 'Remote Identity Assertion authz rules' " 124 "EQUALITY caseIgnoreMatch " 125 "SYNTAX OMsDirectoryString " 126 "X-ORDERED 'VALUES' )", 127 NULL, NULL }, 128 { "rebind-as-user", "true|FALSE", 1, 2, 0, 129 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, 130 ldap_back_cf_gen, "( OLcfgDbAt:3.10 " 131 "NAME 'olcDbRebindAsUser' " 132 "DESC 'Rebind as user' " 133 "EQUALITY booleanMatch " 134 "SYNTAX OMsBoolean " 135 "SINGLE-VALUE )", 136 NULL, NULL }, 137 { "chase-referrals", "true|FALSE", 2, 2, 0, 138 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, 139 ldap_back_cf_gen, "( OLcfgDbAt:3.11 " 140 "NAME 'olcDbChaseReferrals' " 141 "DESC 'Chase referrals' " 142 "EQUALITY booleanMatch " 143 "SYNTAX OMsBoolean " 144 "SINGLE-VALUE )", 145 NULL, NULL }, 146 { "t-f-support", "true|FALSE|discover", 2, 2, 0, 147 ARG_MAGIC|LDAP_BACK_CFG_T_F, 148 ldap_back_cf_gen, "( OLcfgDbAt:3.12 " 149 "NAME 'olcDbTFSupport' " 150 "DESC 'Absolute filters support' " 151 "EQUALITY caseIgnoreMatch " 152 "SYNTAX OMsDirectoryString " 153 "SINGLE-VALUE )", 154 NULL, NULL }, 155 { "proxy-whoami", "true|FALSE", 1, 2, 0, 156 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI, 157 ldap_back_cf_gen, "( OLcfgDbAt:3.13 " 158 "NAME 'olcDbProxyWhoAmI' " 159 "DESC 'Proxy whoAmI exop' " 160 "EQUALITY booleanMatch " 161 "SYNTAX OMsBoolean " 162 "SINGLE-VALUE )", 163 NULL, NULL }, 164 { "timeout", "timeout(list)", 2, 0, 0, 165 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, 166 ldap_back_cf_gen, "( OLcfgDbAt:3.14 " 167 "NAME 'olcDbTimeout' " 168 "DESC 'Per-operation timeouts' " 169 "EQUALITY caseIgnoreMatch " 170 "SYNTAX OMsDirectoryString " 171 "SINGLE-VALUE )", 172 NULL, NULL }, 173 { "idle-timeout", "timeout", 2, 2, 0, 174 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, 175 ldap_back_cf_gen, "( OLcfgDbAt:3.15 " 176 "NAME 'olcDbIdleTimeout' " 177 "DESC 'connection idle timeout' " 178 "EQUALITY caseIgnoreMatch " 179 "SYNTAX OMsDirectoryString " 180 "SINGLE-VALUE )", 181 NULL, NULL }, 182 { "conn-ttl", "ttl", 2, 2, 0, 183 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL, 184 ldap_back_cf_gen, "( OLcfgDbAt:3.16 " 185 "NAME 'olcDbConnTtl' " 186 "DESC 'connection ttl' " 187 "EQUALITY caseIgnoreMatch " 188 "SYNTAX OMsDirectoryString " 189 "SINGLE-VALUE )", 190 NULL, NULL }, 191 { "network-timeout", "timeout", 2, 2, 0, 192 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, 193 ldap_back_cf_gen, "( OLcfgDbAt:3.17 " 194 "NAME 'olcDbNetworkTimeout' " 195 "DESC 'connection network timeout' " 196 "EQUALITY caseIgnoreMatch " 197 "SYNTAX OMsDirectoryString " 198 "SINGLE-VALUE )", 199 NULL, NULL }, 200 { "protocol-version", "version", 2, 2, 0, 201 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, 202 ldap_back_cf_gen, "( OLcfgDbAt:3.18 " 203 "NAME 'olcDbProtocolVersion' " 204 "DESC 'protocol version' " 205 "EQUALITY integerMatch " 206 "SYNTAX OMsInteger " 207 "SINGLE-VALUE )", 208 NULL, NULL }, 209 { "single-conn", "true|FALSE", 2, 2, 0, 210 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN, 211 ldap_back_cf_gen, "( OLcfgDbAt:3.19 " 212 "NAME 'olcDbSingleConn' " 213 "DESC 'cache a single connection per identity' " 214 "EQUALITY booleanMatch " 215 "SYNTAX OMsBoolean " 216 "SINGLE-VALUE )", 217 NULL, NULL }, 218 { "cancel", "ABANDON|ignore|exop", 2, 2, 0, 219 ARG_MAGIC|LDAP_BACK_CFG_CANCEL, 220 ldap_back_cf_gen, "( OLcfgDbAt:3.20 " 221 "NAME 'olcDbCancel' " 222 "DESC 'abandon/ignore/exop operations when appropriate' " 223 "EQUALITY caseIgnoreMatch " 224 "SYNTAX OMsDirectoryString " 225 "SINGLE-VALUE )", 226 NULL, NULL }, 227 { "quarantine", "retrylist", 2, 2, 0, 228 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, 229 ldap_back_cf_gen, "( OLcfgDbAt:3.21 " 230 "NAME 'olcDbQuarantine' " 231 "DESC 'Quarantine database if connection fails and retry according to rule' " 232 "EQUALITY caseIgnoreMatch " 233 "SYNTAX OMsDirectoryString " 234 "SINGLE-VALUE )", 235 NULL, NULL }, 236 { "use-temporary-conn", "true|FALSE", 2, 2, 0, 237 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP, 238 ldap_back_cf_gen, "( OLcfgDbAt:3.22 " 239 "NAME 'olcDbUseTemporaryConn' " 240 "DESC 'Use temporary connections if the cached one is busy' " 241 "EQUALITY booleanMatch " 242 "SYNTAX OMsBoolean " 243 "SINGLE-VALUE )", 244 NULL, NULL }, 245 { "conn-pool-max", "<n>", 2, 2, 0, 246 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, 247 ldap_back_cf_gen, "( OLcfgDbAt:3.23 " 248 "NAME 'olcDbConnectionPoolMax' " 249 "DESC 'Max size of privileged connections pool' " 250 "EQUALITY integerMatch " 251 "SYNTAX OMsInteger " 252 "SINGLE-VALUE )", 253 NULL, NULL }, 254#ifdef SLAP_CONTROL_X_SESSION_TRACKING 255 { "session-tracking-request", "true|FALSE", 2, 2, 0, 256 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, 257 ldap_back_cf_gen, "( OLcfgDbAt:3.24 " 258 "NAME 'olcDbSessionTrackingRequest' " 259 "DESC 'Add session tracking control to proxied requests' " 260 "EQUALITY booleanMatch " 261 "SYNTAX OMsBoolean " 262 "SINGLE-VALUE )", 263 NULL, NULL }, 264#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 265 { "norefs", "true|FALSE", 2, 2, 0, 266 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS, 267 ldap_back_cf_gen, "( OLcfgDbAt:3.25 " 268 "NAME 'olcDbNoRefs' " 269 "DESC 'Do not return search reference responses' " 270 "EQUALITY booleanMatch " 271 "SYNTAX OMsBoolean " 272 "SINGLE-VALUE )", 273 NULL, NULL }, 274 { "noundeffilter", "true|FALSE", 2, 2, 0, 275 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER, 276 ldap_back_cf_gen, "( OLcfgDbAt:3.26 " 277 "NAME 'olcDbNoUndefFilter' " 278 "DESC 'Do not propagate undefined search filters' " 279 "EQUALITY booleanMatch " 280 "SYNTAX OMsBoolean " 281 "SINGLE-VALUE )", 282 NULL, NULL }, 283 { "onerr", "CONTINUE|report|stop", 2, 2, 0, 284 ARG_MAGIC|LDAP_BACK_CFG_ONERR, 285 ldap_back_cf_gen, "( OLcfgDbAt:3.108 " 286 "NAME 'olcDbOnErr' " 287 "DESC 'error handling' " 288 "EQUALITY caseIgnoreMatch " 289 "SYNTAX OMsDirectoryString " 290 "SINGLE-VALUE )", 291 NULL, NULL }, 292 { "idassert-passThru", "authzRule", 2, 2, 0, 293 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSTHRU, 294 ldap_back_cf_gen, "( OLcfgDbAt:3.27 " 295 "NAME 'olcDbIDAssertPassThru' " 296 "DESC 'Remote Identity Assertion passthru rules' " 297 "EQUALITY caseIgnoreMatch " 298 "SYNTAX OMsDirectoryString " 299 "X-ORDERED 'VALUES' )", 300 NULL, NULL }, 301 { "omit-unknown-schema", "true|FALSE", 2, 2, 0, 302 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_OMIT_UNKNOWN_SCHEMA, 303 ldap_back_cf_gen, "( OLcfgDbAt:3.28 " 304 "NAME 'olcDbRemoveUnknownSchema' " 305 "DESC 'Omit unknown schema when returning search results' " 306 "EQUALITY booleanMatch " 307 "SYNTAX OMsBoolean " 308 "SINGLE-VALUE )", 309 NULL, NULL }, 310 { "keepalive", "keepalive", 2, 2, 0, 311 ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE, 312 ldap_back_cf_gen, "( OLcfgDbAt:3.29 " 313 "NAME 'olcDbKeepalive' " 314 "DESC 'TCP keepalive' " 315 "EQUALITY caseIgnoreMatch " 316 "SYNTAX OMsDirectoryString " 317 "SINGLE-VALUE )", 318 NULL, NULL }, 319 { "tcp-user-timeout", "milliseconds", 2, 2, 0, 320 ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT, 321 ldap_back_cf_gen, "( OLcfgDbAt:3.30 " 322 "NAME 'olcDbTcpUserTimeout' " 323 "DESC 'TCP User Timeout' " 324 "SYNTAX OMsInteger " 325 "SINGLE-VALUE )", 326 NULL, NULL }, 327 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 328 NULL, NULL, NULL, NULL } 329}; 330 331static ConfigOCs ldapocs[] = { 332 { "( OLcfgDbOc:3.1 " 333 "NAME 'olcLDAPConfig' " 334 "DESC 'LDAP backend configuration' " 335 "SUP olcDatabaseConfig " 336 "MAY ( olcDbURI " 337 "$ olcDbStartTLS " 338 "$ olcDbACLBind " 339 "$ olcDbIDAssertBind " 340 "$ olcDbIDAssertAuthzFrom " 341 "$ olcDbIDAssertPassThru " 342 "$ olcDbRebindAsUser " 343 "$ olcDbChaseReferrals " 344 "$ olcDbTFSupport " 345 "$ olcDbProxyWhoAmI " 346 "$ olcDbTimeout " 347 "$ olcDbIdleTimeout " 348 "$ olcDbConnTtl " 349 "$ olcDbNetworkTimeout " 350 "$ olcDbProtocolVersion " 351 "$ olcDbSingleConn " 352 "$ olcDbCancel " 353 "$ olcDbQuarantine " 354 "$ olcDbUseTemporaryConn " 355 "$ olcDbConnectionPoolMax " 356#ifdef SLAP_CONTROL_X_SESSION_TRACKING 357 "$ olcDbSessionTrackingRequest " 358#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 359 "$ olcDbNoRefs " 360 "$ olcDbNoUndefFilter " 361 "$ olcDbOnErr " 362 "$ olcDbKeepalive " 363 ") )", 364 Cft_Database, ldapcfg}, 365 { NULL, 0, NULL } 366}; 367 368static ConfigTable pbindcfg[] = { 369 { "uri", "uri", 2, 2, 0, 370 ARG_MAGIC|LDAP_BACK_CFG_URI, 371 ldap_pbind_cf_gen, "( OLcfgDbAt:0.14 " 372 "NAME 'olcDbURI' " 373 "DESC 'URI (list) for remote DSA' " 374 "SYNTAX OMsDirectoryString " 375 "SINGLE-VALUE )", 376 NULL, NULL }, 377 { "tls", "what", 2, 0, 0, 378 ARG_MAGIC|LDAP_BACK_CFG_TLS, 379 ldap_pbind_cf_gen, "( OLcfgDbAt:3.1 " 380 "NAME 'olcDbStartTLS' " 381 "DESC 'StartTLS' " 382 "SYNTAX OMsDirectoryString " 383 "SINGLE-VALUE )", 384 NULL, NULL }, 385 { "network-timeout", "timeout", 2, 2, 0, 386 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, 387 ldap_pbind_cf_gen, "( OLcfgDbAt:3.17 " 388 "NAME 'olcDbNetworkTimeout' " 389 "DESC 'connection network timeout' " 390 "SYNTAX OMsDirectoryString " 391 "SINGLE-VALUE )", 392 NULL, NULL }, 393 { "quarantine", "retrylist", 2, 2, 0, 394 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, 395 ldap_pbind_cf_gen, "( OLcfgDbAt:3.21 " 396 "NAME 'olcDbQuarantine' " 397 "DESC 'Quarantine database if connection fails and retry according to rule' " 398 "SYNTAX OMsDirectoryString " 399 "SINGLE-VALUE )", 400 NULL, NULL }, 401 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 402 NULL, NULL, NULL, NULL } 403}; 404 405static ConfigOCs pbindocs[] = { 406 { "( OLcfgOvOc:3.3 " 407 "NAME 'olcPBindConfig' " 408 "DESC 'Proxy Bind configuration' " 409 "SUP olcOverlayConfig " 410 "MUST olcDbURI " 411 "MAY ( olcDbStartTLS " 412 "$ olcDbNetworkTimeout " 413 "$ olcDbQuarantine " 414 ") )", 415 Cft_Overlay, pbindcfg}, 416 { NULL, 0, NULL } 417}; 418 419static slap_verbmasks idassert_mode[] = { 420 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF }, 421 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS }, 422 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT }, 423 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY }, 424 { BER_BVNULL, 0 } 425}; 426 427static slap_verbmasks tls_mode[] = { 428 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK }, 429 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS }, 430 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK }, 431 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS }, 432 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS }, 433 { BER_BVC( "none" ), LDAP_BACK_F_NONE }, 434 { BER_BVNULL, 0 } 435}; 436 437static slap_verbmasks t_f_mode[] = { 438 { BER_BVC( "yes" ), LDAP_BACK_F_T_F }, 439 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER }, 440 { BER_BVC( "no" ), LDAP_BACK_F_NONE }, 441 { BER_BVNULL, 0 } 442}; 443 444static slap_verbmasks cancel_mode[] = { 445 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE }, 446 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP }, 447 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER }, 448 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON }, 449 { BER_BVNULL, 0 } 450}; 451 452static slap_verbmasks onerr_mode[] = { 453 { BER_BVC( "stop" ), LDAP_BACK_F_ONERR_STOP }, 454 { BER_BVC( "report" ), LDAP_BACK_F_ONERR_STOP }, /* same behavior */ 455 { BER_BVC( "continue" ), LDAP_BACK_F_NONE }, 456 { BER_BVNULL, 0 } 457}; 458 459/* see enum in slap.h */ 460static slap_cf_aux_table timeout_table[] = { 461 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL }, 462 /* unbind makes no sense */ 463 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL }, 464 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL }, 465 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL }, 466 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL }, 467 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL }, 468 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL }, 469 /* abandon makes little sense */ 470#if 0 /* not implemented yet */ 471 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL }, 472#endif 473 { BER_BVNULL, 0, 0, 0, NULL } 474}; 475 476int 477slap_retry_info_parse( 478 char *in, 479 slap_retry_info_t *ri, 480 char *buf, 481 ber_len_t buflen ) 482{ 483 char **retrylist = NULL; 484 int rc = 0; 485 int i; 486 487 slap_str2clist( &retrylist, in, " ;" ); 488 if ( retrylist == NULL ) { 489 return 1; 490 } 491 492 for ( i = 0; retrylist[ i ] != NULL; i++ ) 493 /* count */ ; 494 495 ri->ri_interval = ch_calloc( sizeof( time_t ), i + 1 ); 496 ri->ri_num = ch_calloc( sizeof( int ), i + 1 ); 497 498 for ( i = 0; retrylist[ i ] != NULL; i++ ) { 499 unsigned long t; 500 char *sep = strchr( retrylist[ i ], ',' ); 501 502 if ( sep == NULL ) { 503 snprintf( buf, buflen, 504 "missing comma in retry pattern #%d \"%s\"", 505 i, retrylist[ i ] ); 506 rc = 1; 507 goto done; 508 } 509 510 *sep++ = '\0'; 511 512 if ( lutil_parse_time( retrylist[ i ], &t ) ) { 513 snprintf( buf, buflen, 514 "unable to parse interval #%d \"%s\"", 515 i, retrylist[ i ] ); 516 rc = 1; 517 goto done; 518 } 519 ri->ri_interval[ i ] = (time_t)t; 520 521 if ( strcmp( sep, "+" ) == 0 ) { 522 if ( retrylist[ i + 1 ] != NULL ) { 523 snprintf( buf, buflen, 524 "extra cruft after retry pattern " 525 "#%d \"%s,+\" with \"forever\" mark", 526 i, retrylist[ i ] ); 527 rc = 1; 528 goto done; 529 } 530 ri->ri_num[ i ] = SLAP_RETRYNUM_FOREVER; 531 532 } else if ( lutil_atoi( &ri->ri_num[ i ], sep ) ) { 533 snprintf( buf, buflen, 534 "unable to parse retry num #%d \"%s\"", 535 i, sep ); 536 rc = 1; 537 goto done; 538 } 539 } 540 541 ri->ri_num[ i ] = SLAP_RETRYNUM_TAIL; 542 543 ri->ri_idx = 0; 544 ri->ri_count = 0; 545 ri->ri_last = (time_t)(-1); 546 547done:; 548 ldap_charray_free( retrylist ); 549 550 if ( rc ) { 551 slap_retry_info_destroy( ri ); 552 } 553 554 return rc; 555} 556 557int 558slap_retry_info_unparse( 559 slap_retry_info_t *ri, 560 struct berval *bvout ) 561{ 562 char buf[ BUFSIZ * 2 ], 563 *ptr = buf; 564 int i, len, restlen = (int) sizeof( buf ); 565 struct berval bv; 566 567 assert( ri != NULL ); 568 assert( bvout != NULL ); 569 570 BER_BVZERO( bvout ); 571 572 for ( i = 0; ri->ri_num[ i ] != SLAP_RETRYNUM_TAIL; i++ ) { 573 if ( i > 0 ) { 574 if ( --restlen <= 0 ) { 575 return 1; 576 } 577 *ptr++ = ';'; 578 } 579 580 if ( lutil_unparse_time( ptr, restlen, ri->ri_interval[i] ) < 0 ) { 581 return 1; 582 } 583 len = (int) strlen( ptr ); 584 if ( (restlen -= len + 1) <= 0 ) { 585 return 1; 586 } 587 ptr += len; 588 *ptr++ = ','; 589 590 if ( ri->ri_num[i] == SLAP_RETRYNUM_FOREVER ) { 591 if ( --restlen <= 0 ) { 592 return 1; 593 } 594 *ptr++ = '+'; 595 596 } else { 597 len = snprintf( ptr, restlen, "%d", ri->ri_num[i] ); 598 if ( (restlen -= len) <= 0 || len < 0 ) { 599 return 1; 600 } 601 ptr += len; 602 } 603 } 604 605 bv.bv_val = buf; 606 bv.bv_len = ptr - buf; 607 ber_dupbv( bvout, &bv ); 608 609 return 0; 610} 611 612void 613slap_retry_info_destroy( 614 slap_retry_info_t *ri ) 615{ 616 assert( ri != NULL ); 617 618 assert( ri->ri_interval != NULL ); 619 ch_free( ri->ri_interval ); 620 ri->ri_interval = NULL; 621 622 assert( ri->ri_num != NULL ); 623 ch_free( ri->ri_num ); 624 ri->ri_num = NULL; 625} 626 627int 628slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si ) 629{ 630 struct berval bv; 631 struct berval in; 632 int rc; 633 634 if ( strcmp( c->argv[ 1 ], "*" ) == 0 635 || strcmp( c->argv[ 1 ], "dn:*" ) == 0 636 || strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 ) 637 { 638 if ( si->si_authz != NULL ) { 639 snprintf( c->cr_msg, sizeof( c->cr_msg ), 640 "\"%s <authz>\": " 641 "\"%s\" conflicts with existing authz rules", 642 c->argv[ 0 ], c->argv[ 1 ] ); 643 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 644 return 1; 645 } 646 647 si->si_flags |= LDAP_BACK_AUTH_AUTHZ_ALL; 648 649 return 0; 650 651 } else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) { 652 snprintf( c->cr_msg, sizeof( c->cr_msg ), 653 "\"%s <authz>\": " 654 "\"<authz>\" conflicts with \"*\"", c->argv[0] ); 655 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 656 return 1; 657 } 658 659 ber_str2bv( c->argv[ 1 ], 0, 0, &in ); 660 rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL ); 661 if ( rc != LDAP_SUCCESS ) { 662 snprintf( c->cr_msg, sizeof( c->cr_msg ), 663 "\"%s <authz>\": " 664 "invalid syntax", c->argv[0] ); 665 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 666 return 1; 667 } 668 669 if ( c->valx == -1 ) { 670 ber_bvarray_add( &si->si_authz, &bv ); 671 672 } else { 673 int i = 0; 674 if ( si->si_authz != NULL ) { 675 for ( ; !BER_BVISNULL( &si->si_authz[ i ] ); i++ ) 676 ; 677 } 678 679 if ( i <= c->valx ) { 680 ber_bvarray_add( &si->si_authz, &bv ); 681 682 } else { 683 BerVarray tmp = ber_memrealloc( si->si_authz, 684 sizeof( struct berval )*( i + 2 ) ); 685 if ( tmp == NULL ) { 686 return -1; 687 } 688 si->si_authz = tmp; 689 for ( ; i > c->valx; i-- ) { 690 si->si_authz[ i ] = si->si_authz[ i - 1 ]; 691 } 692 si->si_authz[ c->valx ] = bv; 693 } 694 } 695 696 return 0; 697} 698 699static int 700slap_idassert_passthru_parse( ConfigArgs *c, slap_idassert_t *si ) 701{ 702 struct berval bv; 703 struct berval in; 704 int rc; 705 706 ber_str2bv( c->argv[ 1 ], 0, 0, &in ); 707 rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL ); 708 if ( rc != LDAP_SUCCESS ) { 709 snprintf( c->cr_msg, sizeof( c->cr_msg ), 710 "\"%s <authz>\": " 711 "invalid syntax", c->argv[0] ); 712 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 713 return 1; 714 } 715 716 if ( c->valx == -1 ) { 717 ber_bvarray_add( &si->si_passthru, &bv ); 718 719 } else { 720 int i = 0; 721 if ( si->si_passthru != NULL ) { 722 for ( ; !BER_BVISNULL( &si->si_passthru[ i ] ); i++ ) 723 ; 724 } 725 726 if ( i <= c->valx ) { 727 ber_bvarray_add( &si->si_passthru, &bv ); 728 729 } else { 730 BerVarray tmp = ber_memrealloc( si->si_passthru, 731 sizeof( struct berval )*( i + 2 ) ); 732 if ( tmp == NULL ) { 733 return -1; 734 } 735 si->si_passthru = tmp; 736 for ( ; i > c->valx; i-- ) { 737 si->si_passthru[ i ] = si->si_passthru[ i - 1 ]; 738 } 739 si->si_passthru[ c->valx ] = bv; 740 } 741 } 742 743 return 0; 744} 745 746int 747slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si ) 748{ 749 int i; 750 751 /* set default */ 752 si->si_mode = LDAP_BACK_IDASSERT_LEGACY; 753 754 for ( i = 1; i < c->argc; i++ ) { 755 if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) { 756 char *argvi = c->argv[ i ] + STRLENOF( "mode=" ); 757 int j; 758 759 j = verb_to_mask( argvi, idassert_mode ); 760 if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) { 761 snprintf( c->cr_msg, sizeof( c->cr_msg ), 762 "\"%s <args>\": " 763 "unknown mode \"%s\"", 764 c->argv[0], argvi ); 765 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 766 return 1; 767 } 768 769 si->si_mode = idassert_mode[ j ].mask; 770 771 } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) { 772 char *argvi = c->argv[ i ] + STRLENOF( "authz=" ); 773 774 if ( strcasecmp( argvi, "native" ) == 0 ) { 775 if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) { 776 snprintf( c->cr_msg, sizeof( c->cr_msg ), 777 "\"%s <args>\": " 778 "authz=\"native\" incompatible " 779 "with auth method", c->argv[0] ); 780 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 781 return 1; 782 } 783 si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ; 784 785 } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) { 786 si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ; 787 788 } else { 789 snprintf( c->cr_msg, sizeof( c->cr_msg ), 790 "\"%s <args>\": " 791 "unknown authz \"%s\"", 792 c->argv[0], argvi ); 793 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 794 return 1; 795 } 796 797 } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) { 798 char *argvi = c->argv[ i ] + STRLENOF( "flags=" ); 799 char **flags = ldap_str2charray( argvi, "," ); 800 int j, err = 0; 801 802 if ( flags == NULL ) { 803 snprintf( c->cr_msg, sizeof( c->cr_msg ), 804 "\"%s <args>\": " 805 "unable to parse flags \"%s\"", 806 c->argv[0], argvi ); 807 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 808 return 1; 809 } 810 811 for ( j = 0; flags[ j ] != NULL; j++ ) { 812 813 if ( strcasecmp( flags[ j ], "override" ) == 0 ) { 814 si->si_flags |= LDAP_BACK_AUTH_OVERRIDE; 815 816 } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) { 817 si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE; 818 819 } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) { 820 si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE ); 821 822 } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) { 823 if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 824 snprintf( c->cr_msg, sizeof( c->cr_msg ), 825 "\"%s <args>\": " 826 "\"obsolete-proxy-authz\" flag " 827 "incompatible with previously issued \"obsolete-encoding-workaround\" flag.", 828 c->argv[0] ); 829 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 830 err = 1; 831 break; 832 833 } else { 834 si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ; 835 } 836 837 } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) { 838 if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 839 snprintf( c->cr_msg, sizeof( c->cr_msg ), 840 "\"%s <args>\": " 841 "\"obsolete-encoding-workaround\" flag " 842 "incompatible with previously issued \"obsolete-proxy-authz\" flag.", 843 c->argv[0] ); 844 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 845 err = 1; 846 break; 847 848 } else { 849 si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND; 850 } 851 852 } else if ( strcasecmp( flags[ j ], "proxy-authz-critical" ) == 0 ) { 853 si->si_flags |= LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL; 854 855 } else if ( strcasecmp( flags[ j ], "proxy-authz-non-critical" ) == 0 ) { 856 si->si_flags &= ~LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL; 857 858 } else if ( strcasecmp( flags[ j ], "dn-none" ) == 0 ) { 859 si->si_flags &= ~LDAP_BACK_AUTH_DN_MASK; 860 861 } else if ( strcasecmp( flags[ j ], "dn-authzid" ) == 0 ) { 862 si->si_flags &= ~LDAP_BACK_AUTH_DN_MASK; 863 si->si_flags |= LDAP_BACK_AUTH_DN_AUTHZID; 864 865 } else if ( strcasecmp( flags[ j ], "dn-whoami" ) == 0 ) { 866 si->si_flags &= ~LDAP_BACK_AUTH_DN_MASK; 867 si->si_flags |= LDAP_BACK_AUTH_DN_WHOAMI; 868 869 } else { 870 snprintf( c->cr_msg, sizeof( c->cr_msg ), 871 "\"%s <args>\": " 872 "unknown flag \"%s\"", 873 c->argv[0], flags[ j ] ); 874 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 875 err = 1; 876 break; 877 } 878 } 879 880 ldap_charray_free( flags ); 881 if ( err ) { 882 return 1; 883 } 884 885 } else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) { 886 snprintf( c->cr_msg, sizeof( c->cr_msg ), 887 "\"%s <args>\": " 888 "unable to parse field \"%s\"", 889 c->argv[0], c->argv[ i ] ); 890 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 891 return 1; 892 } 893 } 894 895 if ( si->si_bc.sb_method == LDAP_AUTH_SIMPLE ) { 896 if ( BER_BVISNULL( &si->si_bc.sb_binddn ) 897 || BER_BVISNULL( &si->si_bc.sb_cred ) ) 898 { 899 snprintf( c->cr_msg, sizeof( c->cr_msg ), 900 "\"%s <args>\": " 901 "SIMPLE needs \"binddn\" and \"credentials\"", c->argv[0] ); 902 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 903 return 1; 904 } 905 906 } else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) { 907 if ( BER_BVISNULL( &si->si_bc.sb_binddn ) && 908 !(si->si_flags & LDAP_BACK_AUTH_DN_MASK) ) 909 { 910 static struct berval authid = BER_BVC("cn=auth"); 911 ber_dupbv( &si->si_bc.sb_binddn, &authid ); 912 } 913 } 914 915 bindconf_tls_defaults( &si->si_bc ); 916#ifdef HAVE_TLS 917 if ( si->si_bc.sb_tls_ctx ) { 918 ldap_pvt_tls_ctx_free( si->si_bc.sb_tls_ctx ); 919 si->si_bc.sb_tls_ctx = NULL; 920 } 921#endif 922 923 return 0; 924} 925 926/* NOTE: temporary, until back-meta is ported to back-config */ 927int 928slap_idassert_passthru_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si ) 929{ 930 ConfigArgs c = { 0 }; 931 char *argv[ 3 ]; 932 933 snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno ); 934 c.argc = 2; 935 c.argv = argv; 936 argv[ 0 ] = "idassert-passThru"; 937 argv[ 1 ] = (char *)arg; 938 argv[ 2 ] = NULL; 939 940 return slap_idassert_passthru_parse( &c, si ); 941} 942 943static int 944ldap_back_cf_gen( ConfigArgs *c ) 945{ 946 ldapinfo_t *li = ( ldapinfo_t * )c->be->be_private; 947 int rc = 0; 948 int i; 949 950 if ( c->op == SLAP_CONFIG_EMIT ) { 951 struct berval bv = BER_BVNULL; 952 953 if ( li == NULL ) { 954 return 1; 955 } 956 957 switch( c->type ) { 958 case LDAP_BACK_CFG_URI: 959 if ( li->li_uri != NULL ) { 960 struct berval bv, bv2; 961 962 ber_str2bv( li->li_uri, 0, 0, &bv ); 963 bv2.bv_len = bv.bv_len + STRLENOF( "\"\"" ); 964 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 965 snprintf( bv2.bv_val, bv2.bv_len + 1, 966 "\"%s\"", bv.bv_val ); 967 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 968 969 } else { 970 rc = 1; 971 } 972 break; 973 974 case LDAP_BACK_CFG_TLS: { 975 struct berval bc = BER_BVNULL, bv2; 976 enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv ); 977 assert( !BER_BVISNULL( &bv ) ); 978 bindconf_tls_unparse( &li->li_tls, &bc ); 979 980 if ( !BER_BVISEMPTY( &bc )) { 981 bv2.bv_len = bv.bv_len + bc.bv_len + 1; 982 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 983 strcpy( bv2.bv_val, bv.bv_val ); 984 bv2.bv_val[bv.bv_len] = ' '; 985 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val ); 986 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 987 988 } else { 989 value_add_one( &c->rvalue_vals, &bv ); 990 } 991 ber_memfree( bc.bv_val ); 992 } 993 break; 994 995 case LDAP_BACK_CFG_ACL_BIND: { 996 int i; 997 998 if ( li->li_acl_authmethod == LDAP_AUTH_NONE ) { 999 return 1; 1000 } 1001 1002 bindconf_unparse( &li->li_acl, &bv ); 1003 1004 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 1005 /* count spaces */ ; 1006 1007 if ( i ) { 1008 bv.bv_len -= i; 1009 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 1010 bv.bv_len + 1 ); 1011 } 1012 1013 ber_bvarray_add( &c->rvalue_vals, &bv ); 1014 break; 1015 } 1016 1017 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 1018 case LDAP_BACK_CFG_IDASSERT_PASSTHRU: { 1019 BerVarray *bvp; 1020 int i; 1021 struct berval bv = BER_BVNULL; 1022 char buf[SLAP_TEXT_BUFLEN]; 1023 1024 switch ( c->type ) { 1025 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: bvp = &li->li_idassert_authz; break; 1026 case LDAP_BACK_CFG_IDASSERT_PASSTHRU: bvp = &li->li_idassert_passthru; break; 1027 default: assert( 0 ); break; 1028 } 1029 1030 if ( *bvp == NULL ) { 1031 if ( bvp == &li->li_idassert_authz 1032 && ( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) 1033 { 1034 BER_BVSTR( &bv, "*" ); 1035 value_add_one( &c->rvalue_vals, &bv ); 1036 1037 } else { 1038 rc = 1; 1039 } 1040 break; 1041 } 1042 1043 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) { 1044 char *ptr; 1045 int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); 1046 bv.bv_len = ((*bvp)[ i ]).bv_len + len; 1047 bv.bv_val = ber_memrealloc( bv.bv_val, bv.bv_len + 1 ); 1048 ptr = bv.bv_val; 1049 ptr = lutil_strcopy( ptr, buf ); 1050 ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len ); 1051 value_add_one( &c->rvalue_vals, &bv ); 1052 } 1053 if ( bv.bv_val ) { 1054 ber_memfree( bv.bv_val ); 1055 } 1056 break; 1057 } 1058 1059 case LDAP_BACK_CFG_IDASSERT_BIND: { 1060 int i; 1061 struct berval bc = BER_BVNULL; 1062 char *ptr; 1063 1064 if ( li->li_idassert_authmethod == LDAP_AUTH_NONE ) { 1065 return 1; 1066 } 1067 1068 if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) { 1069 ber_len_t len; 1070 1071 switch ( li->li_idassert_mode ) { 1072 case LDAP_BACK_IDASSERT_OTHERID: 1073 case LDAP_BACK_IDASSERT_OTHERDN: 1074 break; 1075 1076 default: { 1077 struct berval mode = BER_BVNULL; 1078 1079 enum_to_verb( idassert_mode, li->li_idassert_mode, &mode ); 1080 if ( BER_BVISNULL( &mode ) ) { 1081 /* there's something wrong... */ 1082 assert( 0 ); 1083 rc = 1; 1084 1085 } else { 1086 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len; 1087 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1088 1089 ptr = lutil_strcopy( bv.bv_val, "mode=" ); 1090 ptr = lutil_strcopy( ptr, mode.bv_val ); 1091 } 1092 break; 1093 } 1094 } 1095 1096 if ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) { 1097 len = bv.bv_len + STRLENOF( "authz=native" ); 1098 1099 if ( !BER_BVISEMPTY( &bv ) ) { 1100 len += STRLENOF( " " ); 1101 } 1102 1103 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1104 1105 ptr = &bv.bv_val[ bv.bv_len ]; 1106 1107 if ( !BER_BVISEMPTY( &bv ) ) { 1108 ptr = lutil_strcopy( ptr, " " ); 1109 } 1110 1111 (void)lutil_strcopy( ptr, "authz=native" ); 1112 } 1113 1114 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" ); 1115 /* flags */ 1116 if ( !BER_BVISEMPTY( &bv ) ) { 1117 len += STRLENOF( " " ); 1118 } 1119 1120 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1121 1122 ptr = &bv.bv_val[ bv.bv_len ]; 1123 1124 if ( !BER_BVISEMPTY( &bv ) ) { 1125 ptr = lutil_strcopy( ptr, " " ); 1126 } 1127 1128 ptr = lutil_strcopy( ptr, "flags=" ); 1129 1130 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 1131 ptr = lutil_strcopy( ptr, "prescriptive" ); 1132 } else { 1133 ptr = lutil_strcopy( ptr, "non-prescriptive" ); 1134 } 1135 1136 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 1137 ptr = lutil_strcopy( ptr, ",override" ); 1138 } 1139 1140 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 1141 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" ); 1142 1143 } else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 1144 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" ); 1145 } 1146 1147 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) { 1148 ptr = lutil_strcopy( ptr, ",proxy-authz-critical" ); 1149 1150 } else { 1151 ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" ); 1152 } 1153 1154 switch ( li->li_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) { 1155 case LDAP_BACK_AUTH_DN_AUTHZID: 1156 ptr = lutil_strcopy( ptr, ",dn-authzid" ); 1157 break; 1158 1159 case LDAP_BACK_AUTH_DN_WHOAMI: 1160 ptr = lutil_strcopy( ptr, ",dn-whoami" ); 1161 break; 1162 1163 default: 1164#if 0 /* implicit */ 1165 ptr = lutil_strcopy( ptr, ",dn-none" ); 1166#endif 1167 break; 1168 } 1169 1170 bv.bv_len = ( ptr - bv.bv_val ); 1171 /* end-of-flags */ 1172 } 1173 1174 bindconf_unparse( &li->li_idassert.si_bc, &bc ); 1175 1176 if ( !BER_BVISNULL( &bv ) ) { 1177 ber_len_t len = bv.bv_len + bc.bv_len; 1178 1179 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1180 1181 assert( bc.bv_val[ 0 ] == ' ' ); 1182 1183 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val ); 1184 free( bc.bv_val ); 1185 bv.bv_len = ptr - bv.bv_val; 1186 1187 } else { 1188 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ ) 1189 /* count spaces */ ; 1190 1191 if ( i ) { 1192 bc.bv_len -= i; 1193 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 ); 1194 } 1195 1196 bv = bc; 1197 } 1198 1199 ber_bvarray_add( &c->rvalue_vals, &bv ); 1200 1201 break; 1202 } 1203 1204 case LDAP_BACK_CFG_REBIND: 1205 c->value_int = LDAP_BACK_SAVECRED( li ); 1206 break; 1207 1208 case LDAP_BACK_CFG_CHASE: 1209 c->value_int = LDAP_BACK_CHASE_REFERRALS( li ); 1210 break; 1211 1212 case LDAP_BACK_CFG_T_F: 1213 enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_T_F_MASK2), &bv ); 1214 if ( BER_BVISNULL( &bv ) ) { 1215 /* there's something wrong... */ 1216 assert( 0 ); 1217 rc = 1; 1218 1219 } else { 1220 value_add_one( &c->rvalue_vals, &bv ); 1221 } 1222 break; 1223 1224 case LDAP_BACK_CFG_WHOAMI: 1225 c->value_int = LDAP_BACK_PROXY_WHOAMI( li ); 1226 break; 1227 1228 case LDAP_BACK_CFG_TIMEOUT: 1229 BER_BVZERO( &bv ); 1230 1231 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1232 if ( li->li_timeout[ i ] != 0 ) { 1233 break; 1234 } 1235 } 1236 1237 if ( i == SLAP_OP_LAST ) { 1238 return 1; 1239 } 1240 1241 slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table ); 1242 1243 if ( BER_BVISNULL( &bv ) ) { 1244 return 1; 1245 } 1246 1247 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 1248 /* count spaces */ ; 1249 1250 if ( i ) { 1251 bv.bv_len -= i; 1252 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 1253 bv.bv_len + 1 ); 1254 } 1255 1256 ber_bvarray_add( &c->rvalue_vals, &bv ); 1257 break; 1258 1259 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 1260 char buf[ SLAP_TEXT_BUFLEN ]; 1261 1262 if ( li->li_idle_timeout == 0 ) { 1263 return 1; 1264 } 1265 1266 lutil_unparse_time( buf, sizeof( buf ), li->li_idle_timeout ); 1267 ber_str2bv( buf, 0, 0, &bv ); 1268 value_add_one( &c->rvalue_vals, &bv ); 1269 } break; 1270 1271 case LDAP_BACK_CFG_CONN_TTL: { 1272 char buf[ SLAP_TEXT_BUFLEN ]; 1273 1274 if ( li->li_conn_ttl == 0 ) { 1275 return 1; 1276 } 1277 1278 lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl ); 1279 ber_str2bv( buf, 0, 0, &bv ); 1280 value_add_one( &c->rvalue_vals, &bv ); 1281 } break; 1282 1283 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 1284 char buf[ SLAP_TEXT_BUFLEN ]; 1285 1286 if ( li->li_network_timeout == 0 ) { 1287 return 1; 1288 } 1289 1290 lutil_unparse_time( buf, sizeof( buf ), li->li_network_timeout ); 1291 ber_str2bv( buf, 0, 0, &bv ); 1292 value_add_one( &c->rvalue_vals, &bv ); 1293 } break; 1294 1295 case LDAP_BACK_CFG_VERSION: 1296 if ( li->li_version == 0 ) { 1297 return 1; 1298 } 1299 1300 c->value_int = li->li_version; 1301 break; 1302 1303 case LDAP_BACK_CFG_SINGLECONN: 1304 c->value_int = LDAP_BACK_SINGLECONN( li ); 1305 break; 1306 1307 case LDAP_BACK_CFG_USETEMP: 1308 c->value_int = LDAP_BACK_USE_TEMPORARIES( li ); 1309 break; 1310 1311 case LDAP_BACK_CFG_CONNPOOLMAX: 1312 c->value_int = li->li_conn_priv_max; 1313 break; 1314 1315 case LDAP_BACK_CFG_CANCEL: { 1316 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2; 1317 1318 if ( LDAP_BACK_CANCEL_DISCOVER( li ) ) { 1319 mask &= ~LDAP_BACK_F_CANCEL_EXOP; 1320 } 1321 enum_to_verb( cancel_mode, (li->li_flags & mask), &bv ); 1322 if ( BER_BVISNULL( &bv ) ) { 1323 /* there's something wrong... */ 1324 assert( 0 ); 1325 rc = 1; 1326 1327 } else { 1328 value_add_one( &c->rvalue_vals, &bv ); 1329 } 1330 } break; 1331 1332 case LDAP_BACK_CFG_QUARANTINE: 1333 if ( !LDAP_BACK_QUARANTINE( li ) ) { 1334 rc = 1; 1335 break; 1336 } 1337 1338 rc = slap_retry_info_unparse( &li->li_quarantine, &bv ); 1339 if ( rc == 0 ) { 1340 ber_bvarray_add( &c->rvalue_vals, &bv ); 1341 } 1342 break; 1343 1344#ifdef SLAP_CONTROL_X_SESSION_TRACKING 1345 case LDAP_BACK_CFG_ST_REQUEST: 1346 c->value_int = LDAP_BACK_ST_REQUEST( li ); 1347 break; 1348#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1349 1350 case LDAP_BACK_CFG_NOREFS: 1351 c->value_int = LDAP_BACK_NOREFS( li ); 1352 break; 1353 1354 case LDAP_BACK_CFG_NOUNDEFFILTER: 1355 c->value_int = LDAP_BACK_NOUNDEFFILTER( li ); 1356 break; 1357 1358 case LDAP_BACK_CFG_OMIT_UNKNOWN_SCHEMA: 1359 c->value_int = LDAP_BACK_OMIT_UNKNOWN_SCHEMA( li ); 1360 break; 1361 1362 case LDAP_BACK_CFG_ONERR: 1363 enum_to_verb( onerr_mode, li->li_flags & LDAP_BACK_F_ONERR_STOP, &bv ); 1364 if ( BER_BVISNULL( &bv )) { 1365 rc = 1; 1366 } else { 1367 value_add_one( &c->rvalue_vals, &bv ); 1368 } 1369 break; 1370 1371 case LDAP_BACK_CFG_KEEPALIVE: { 1372 struct berval bv; 1373 char buf[AC_LINE_MAX]; 1374 bv.bv_len = AC_LINE_MAX; 1375 bv.bv_val = &buf[0]; 1376 slap_keepalive_parse(&bv, &li->li_tls.sb_keepalive, 0, 0, 1); 1377 value_add_one( &c->rvalue_vals, &bv ); 1378 break; 1379 } 1380 1381 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1382 c->value_uint = li->li_tls.sb_tcp_user_timeout; 1383 break; 1384 1385 default: 1386 /* FIXME: we need to handle all... */ 1387 assert( 0 ); 1388 break; 1389 } 1390 return rc; 1391 1392 } else if ( c->op == LDAP_MOD_DELETE ) { 1393 switch( c->type ) { 1394 case LDAP_BACK_CFG_URI: 1395 if ( li->li_uri != NULL ) { 1396 ch_free( li->li_uri ); 1397 li->li_uri = NULL; 1398 1399 assert( li->li_bvuri != NULL ); 1400 ber_bvarray_free( li->li_bvuri ); 1401 li->li_bvuri = NULL; 1402 } 1403 1404 /* better cleanup the cached connections... */ 1405 /* NOTE: don't worry about locking: if we got here, 1406 * other threads are suspended. */ 1407 if ( li->li_conninfo.lai_tree != NULL ) { 1408 ldap_tavl_free( li->li_conninfo.lai_tree, ldap_back_conn_free ); 1409 li->li_conninfo.lai_tree = NULL; 1410 } 1411 1412 break; 1413 1414 case LDAP_BACK_CFG_TLS: 1415 rc = 1; 1416 break; 1417 1418 case LDAP_BACK_CFG_ACL_BIND: 1419 bindconf_free( &li->li_acl ); 1420 break; 1421 1422 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 1423 case LDAP_BACK_CFG_IDASSERT_PASSTHRU: { 1424 BerVarray *bvp; 1425 1426 switch ( c->type ) { 1427 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: bvp = &li->li_idassert_authz; break; 1428 case LDAP_BACK_CFG_IDASSERT_PASSTHRU: bvp = &li->li_idassert_passthru; break; 1429 default: assert( 0 ); break; 1430 } 1431 1432 if ( c->valx < 0 ) { 1433 if ( *bvp != NULL ) { 1434 ber_bvarray_free( *bvp ); 1435 *bvp = NULL; 1436 } 1437 1438 } else { 1439 int i; 1440 1441 if ( *bvp == NULL ) { 1442 rc = 1; 1443 break; 1444 } 1445 1446 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) 1447 ; 1448 1449 if ( i >= c->valx ) { 1450 rc = 1; 1451 break; 1452 } 1453 ber_memfree( ((*bvp)[ c->valx ]).bv_val ); 1454 for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) { 1455 (*bvp)[ i ] = (*bvp)[ i + 1 ]; 1456 } 1457 BER_BVZERO( &((*bvp)[ i ]) ); 1458 } 1459 } break; 1460 1461 case LDAP_BACK_CFG_IDASSERT_BIND: 1462 bindconf_free( &li->li_idassert.si_bc ); 1463 memset( &li->li_idassert, 0, sizeof( slap_idassert_t ) ); 1464 break; 1465 1466 case LDAP_BACK_CFG_REBIND: 1467 case LDAP_BACK_CFG_CHASE: 1468 case LDAP_BACK_CFG_T_F: 1469 case LDAP_BACK_CFG_WHOAMI: 1470 case LDAP_BACK_CFG_CANCEL: 1471 rc = 1; 1472 break; 1473 1474 case LDAP_BACK_CFG_TIMEOUT: 1475 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1476 li->li_timeout[ i ] = 0; 1477 } 1478 break; 1479 1480 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1481 li->li_idle_timeout = 0; 1482 break; 1483 1484 case LDAP_BACK_CFG_CONN_TTL: 1485 li->li_conn_ttl = 0; 1486 break; 1487 1488 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1489 li->li_network_timeout = 0; 1490 break; 1491 1492 case LDAP_BACK_CFG_VERSION: 1493 li->li_version = 0; 1494 break; 1495 1496 case LDAP_BACK_CFG_SINGLECONN: 1497 li->li_flags &= ~LDAP_BACK_F_SINGLECONN; 1498 break; 1499 1500 case LDAP_BACK_CFG_USETEMP: 1501 li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 1502 break; 1503 1504 case LDAP_BACK_CFG_CONNPOOLMAX: 1505 li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN; 1506 break; 1507 1508 case LDAP_BACK_CFG_QUARANTINE: 1509 if ( !LDAP_BACK_QUARANTINE( li ) ) { 1510 break; 1511 } 1512 1513 slap_retry_info_destroy( &li->li_quarantine ); 1514 ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex ); 1515 li->li_isquarantined = 0; 1516 li->li_flags &= ~LDAP_BACK_F_QUARANTINE; 1517 break; 1518 1519#ifdef SLAP_CONTROL_X_SESSION_TRACKING 1520 case LDAP_BACK_CFG_ST_REQUEST: 1521 li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; 1522 break; 1523#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1524 1525 case LDAP_BACK_CFG_NOREFS: 1526 li->li_flags &= ~LDAP_BACK_F_NOREFS; 1527 break; 1528 1529 case LDAP_BACK_CFG_NOUNDEFFILTER: 1530 li->li_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 1531 break; 1532 1533 case LDAP_BACK_CFG_OMIT_UNKNOWN_SCHEMA: 1534 li->li_flags &= ~LDAP_BACK_F_OMIT_UNKNOWN_SCHEMA; 1535 break; 1536 1537 case LDAP_BACK_CFG_ONERR: 1538 li->li_flags &= ~LDAP_BACK_F_ONERR_STOP; 1539 break; 1540 1541 case LDAP_BACK_CFG_KEEPALIVE: 1542 li->li_tls.sb_keepalive.sk_idle = 0; 1543 li->li_tls.sb_keepalive.sk_probes = 0; 1544 li->li_tls.sb_keepalive.sk_interval = 0; 1545 break; 1546 1547 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1548 li->li_tls.sb_tcp_user_timeout = 0; 1549 break; 1550 1551 default: 1552 /* FIXME: we need to handle all... */ 1553 assert( 0 ); 1554 break; 1555 } 1556 return rc; 1557 1558 } 1559 1560 switch( c->type ) { 1561 case LDAP_BACK_CFG_URI: { 1562 LDAPURLDesc *tmpludp, *lud; 1563 char **urllist = NULL; 1564 int urlrc = LDAP_URL_SUCCESS, i; 1565 1566 if ( li->li_uri != NULL ) { 1567 ch_free( li->li_uri ); 1568 li->li_uri = NULL; 1569 1570 assert( li->li_bvuri != NULL ); 1571 ber_bvarray_free( li->li_bvuri ); 1572 li->li_bvuri = NULL; 1573 } 1574 1575 /* PARANOID: DN and more are not required nor allowed */ 1576 urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE ); 1577 if ( urlrc != LDAP_URL_SUCCESS ) { 1578 char *why; 1579 1580 switch ( urlrc ) { 1581 case LDAP_URL_ERR_MEM: 1582 why = "no memory"; 1583 break; 1584 case LDAP_URL_ERR_PARAM: 1585 why = "parameter is bad"; 1586 break; 1587 case LDAP_URL_ERR_BADSCHEME: 1588 why = "URL doesn't begin with \"[c]ldap[si]://\""; 1589 break; 1590 case LDAP_URL_ERR_BADENCLOSURE: 1591 why = "URL is missing trailing \">\""; 1592 break; 1593 case LDAP_URL_ERR_BADURL: 1594 why = "URL is bad"; 1595 break; 1596 case LDAP_URL_ERR_BADHOST: 1597 why = "host/port is bad"; 1598 break; 1599 case LDAP_URL_ERR_BADATTRS: 1600 why = "bad (or missing) attributes"; 1601 break; 1602 case LDAP_URL_ERR_BADSCOPE: 1603 why = "scope string is invalid (or missing)"; 1604 break; 1605 case LDAP_URL_ERR_BADFILTER: 1606 why = "bad or missing filter"; 1607 break; 1608 case LDAP_URL_ERR_BADEXTS: 1609 why = "bad or missing extensions"; 1610 break; 1611 default: 1612 why = "unknown reason"; 1613 break; 1614 } 1615 snprintf( c->cr_msg, sizeof( c->cr_msg), 1616 "unable to parse uri \"%s\" " 1617 "in \"uri <uri>\" line: %s", 1618 c->value_string, why ); 1619 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1620 urlrc = 1; 1621 goto done_url; 1622 } 1623 1624 for ( i = 0, tmpludp = lud; 1625 tmpludp; 1626 i++, tmpludp = tmpludp->lud_next ) 1627 { 1628 if ( ( tmpludp->lud_dn != NULL 1629 && tmpludp->lud_dn[0] != '\0' ) 1630 || tmpludp->lud_attrs != NULL 1631 /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */ 1632 || tmpludp->lud_filter != NULL 1633 || tmpludp->lud_exts != NULL ) 1634 { 1635 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1636 "warning, only protocol, " 1637 "host and port allowed " 1638 "in \"uri <uri>\" statement " 1639 "for uri #%d of \"%s\"", 1640 i, c->argv[ 1 ] ); 1641 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1642 } 1643 } 1644 1645 for ( i = 0, tmpludp = lud; 1646 tmpludp; 1647 i++, tmpludp = tmpludp->lud_next ) 1648 /* just count */ 1649 ; 1650 urllist = ch_calloc( sizeof( char * ), i + 1 ); 1651 1652 for ( i = 0, tmpludp = lud; 1653 tmpludp; 1654 i++, tmpludp = tmpludp->lud_next ) 1655 { 1656 LDAPURLDesc tmplud; 1657 1658 tmplud = *tmpludp; 1659 tmplud.lud_dn = ""; 1660 tmplud.lud_attrs = NULL; 1661 tmplud.lud_filter = NULL; 1662 if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) { 1663 tmplud.lud_exts = NULL; 1664 tmplud.lud_crit_exts = 0; 1665 } 1666 1667 urllist[ i ] = ldap_url_desc2str( &tmplud ); 1668 1669 if ( urllist[ i ] == NULL ) { 1670 snprintf( c->cr_msg, sizeof( c->cr_msg), 1671 "unable to rebuild uri " 1672 "in \"uri <uri>\" statement " 1673 "for \"%s\"", 1674 c->argv[ 1 ] ); 1675 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1676 urlrc = 1; 1677 goto done_url; 1678 } 1679 } 1680 1681 li->li_uri = ldap_charray2str( urllist, " " ); 1682 for ( i = 0; urllist[ i ] != NULL; i++ ) { 1683 struct berval bv; 1684 1685 ber_str2bv( urllist[ i ], 0, 0, &bv ); 1686 ber_bvarray_add( &li->li_bvuri, &bv ); 1687 urllist[ i ] = NULL; 1688 } 1689 ldap_memfree( urllist ); 1690 urllist = NULL; 1691 1692done_url:; 1693 if ( urllist ) { 1694 ldap_charray_free( urllist ); 1695 } 1696 if ( lud ) { 1697 ldap_free_urllist( lud ); 1698 } 1699 if ( urlrc != LDAP_URL_SUCCESS ) { 1700 return 1; 1701 } 1702 break; 1703 } 1704 1705 case LDAP_BACK_CFG_TLS: 1706 i = verb_to_mask( c->argv[1], tls_mode ); 1707 if ( BER_BVISNULL( &tls_mode[i].word ) ) { 1708 return 1; 1709 } 1710 li->li_flags &= ~LDAP_BACK_F_TLS_MASK; 1711 li->li_flags |= tls_mode[i].mask; 1712 if ( c->argc > 2 ) { 1713 for ( i=2; i<c->argc; i++ ) { 1714 if ( bindconf_tls_parse( c->argv[i], &li->li_tls )) 1715 return 1; 1716 } 1717 bindconf_tls_defaults( &li->li_tls ); 1718 } 1719#ifdef HAVE_TLS 1720 if ( li->li_tls.sb_tls_ctx ) { 1721 ldap_pvt_tls_ctx_free( li->li_tls.sb_tls_ctx ); 1722 li->li_tls.sb_tls_ctx = NULL; 1723 } 1724#endif 1725 break; 1726 1727 case LDAP_BACK_CFG_ACL_BIND: 1728 for ( i = 1; i < c->argc; i++ ) { 1729 if ( bindconf_parse( c->argv[ i ], &li->li_acl ) ) { 1730 return 1; 1731 } 1732 } 1733 bindconf_tls_defaults( &li->li_acl ); 1734#ifdef HAVE_TLS 1735 if ( li->li_acl.sb_tls_ctx ) { 1736 ldap_pvt_tls_ctx_free( li->li_acl.sb_tls_ctx ); 1737 li->li_acl.sb_tls_ctx = NULL; 1738 } 1739#endif 1740 break; 1741 1742 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 1743 rc = slap_idassert_authzfrom_parse( c, &li->li_idassert ); 1744 break; 1745 1746 case LDAP_BACK_CFG_IDASSERT_PASSTHRU: 1747 rc = slap_idassert_passthru_parse( c, &li->li_idassert ); 1748 break; 1749 1750 case LDAP_BACK_CFG_IDASSERT_BIND: 1751 rc = slap_idassert_parse( c, &li->li_idassert ); 1752 break; 1753 1754 case LDAP_BACK_CFG_REBIND: 1755 if ( c->argc == 1 || c->value_int ) { 1756 li->li_flags |= LDAP_BACK_F_SAVECRED; 1757 1758 } else { 1759 li->li_flags &= ~LDAP_BACK_F_SAVECRED; 1760 } 1761 break; 1762 1763 case LDAP_BACK_CFG_CHASE: 1764 if ( c->argc == 1 || c->value_int ) { 1765 li->li_flags |= LDAP_BACK_F_CHASE_REFERRALS; 1766 1767 } else { 1768 li->li_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 1769 } 1770 break; 1771 1772 case LDAP_BACK_CFG_T_F: { 1773 slap_mask_t mask; 1774 1775 i = verb_to_mask( c->argv[1], t_f_mode ); 1776 if ( BER_BVISNULL( &t_f_mode[i].word ) ) { 1777 return 1; 1778 } 1779 1780 mask = t_f_mode[i].mask; 1781 1782 if ( LDAP_BACK_ISOPEN( li ) 1783 && mask == LDAP_BACK_F_T_F_DISCOVER 1784 && !LDAP_BACK_T_F( li ) ) 1785 { 1786 slap_bindconf sb = { BER_BVNULL }; 1787 int rc; 1788 1789 if ( li->li_uri == NULL ) { 1790 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1791 "need URI to discover absolute filters support " 1792 "in \"t-f-support discover\"" ); 1793 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1794 return 1; 1795 } 1796 1797 ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri ); 1798 sb.sb_version = li->li_version; 1799 sb.sb_method = LDAP_AUTH_SIMPLE; 1800 BER_BVSTR( &sb.sb_binddn, "" ); 1801 1802 rc = slap_discover_feature( &sb, 1803 slap_schema.si_ad_supportedFeatures->ad_cname.bv_val, 1804 LDAP_FEATURE_ABSOLUTE_FILTERS ); 1805 if ( rc == LDAP_COMPARE_TRUE ) { 1806 mask |= LDAP_BACK_F_T_F; 1807 } 1808 } 1809 1810 li->li_flags &= ~LDAP_BACK_F_T_F_MASK2; 1811 li->li_flags |= mask; 1812 } break; 1813 1814 case LDAP_BACK_CFG_WHOAMI: 1815 if ( c->argc == 1 || c->value_int ) { 1816 li->li_flags |= LDAP_BACK_F_PROXY_WHOAMI; 1817 load_extop( (struct berval *)&slap_EXOP_WHOAMI, 1818 0, ldap_back_exop_whoami ); 1819 1820 } else { 1821 li->li_flags &= ~LDAP_BACK_F_PROXY_WHOAMI; 1822 } 1823 break; 1824 1825 case LDAP_BACK_CFG_TIMEOUT: 1826 for ( i = 1; i < c->argc; i++ ) { 1827 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) { 1828 int j; 1829 unsigned u; 1830 1831 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) { 1832 snprintf( c->cr_msg, sizeof( c->cr_msg), 1833 "unable to parse timeout \"%s\"", 1834 c->argv[ i ] ); 1835 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1836 return 1; 1837 } 1838 1839 for ( j = 0; j < SLAP_OP_LAST; j++ ) { 1840 li->li_timeout[ j ] = u; 1841 } 1842 1843 continue; 1844 } 1845 1846 if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) { 1847 snprintf( c->cr_msg, sizeof( c->cr_msg), 1848 "unable to parse timeout \"%s\"", 1849 c->argv[ i ] ); 1850 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1851 return 1; 1852 } 1853 } 1854 break; 1855 1856 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 1857 unsigned long t; 1858 1859 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1860 snprintf( c->cr_msg, sizeof( c->cr_msg), 1861 "unable to parse idle timeout \"%s\"", 1862 c->argv[ 1 ] ); 1863 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1864 return 1; 1865 } 1866 li->li_idle_timeout = (time_t)t; 1867 } break; 1868 1869 case LDAP_BACK_CFG_CONN_TTL: { 1870 unsigned long t; 1871 1872 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1873 snprintf( c->cr_msg, sizeof( c->cr_msg), 1874 "unable to parse conn ttl\"%s\"", 1875 c->argv[ 1 ] ); 1876 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1877 return 1; 1878 } 1879 li->li_conn_ttl = (time_t)t; 1880 } break; 1881 1882 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 1883 unsigned long t; 1884 1885 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1886 snprintf( c->cr_msg, sizeof( c->cr_msg), 1887 "unable to parse network timeout \"%s\"", 1888 c->argv[ 1 ] ); 1889 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1890 return 1; 1891 } 1892 li->li_network_timeout = (time_t)t; 1893 } break; 1894 1895 case LDAP_BACK_CFG_VERSION: 1896 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) { 1897 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1898 "unsupported version \"%s\" " 1899 "in \"protocol-version <version>\"", 1900 c->argv[ 1 ] ); 1901 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1902 return 1; 1903 } 1904 1905 li->li_version = c->value_int; 1906 break; 1907 1908 case LDAP_BACK_CFG_SINGLECONN: 1909 if ( c->value_int ) { 1910 li->li_flags |= LDAP_BACK_F_SINGLECONN; 1911 1912 } else { 1913 li->li_flags &= ~LDAP_BACK_F_SINGLECONN; 1914 } 1915 break; 1916 1917 case LDAP_BACK_CFG_USETEMP: 1918 if ( c->value_int ) { 1919 li->li_flags |= LDAP_BACK_F_USE_TEMPORARIES; 1920 1921 } else { 1922 li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 1923 } 1924 break; 1925 1926 case LDAP_BACK_CFG_CONNPOOLMAX: 1927 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN 1928 || c->value_int > LDAP_BACK_CONN_PRIV_MAX ) 1929 { 1930 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1931 "invalid max size " "of privileged " 1932 "connections pool \"%s\" " 1933 "in \"conn-pool-max <n> " 1934 "(must be between %d and %d)\"", 1935 c->argv[ 1 ], 1936 LDAP_BACK_CONN_PRIV_MIN, 1937 LDAP_BACK_CONN_PRIV_MAX ); 1938 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1939 return 1; 1940 } 1941 li->li_conn_priv_max = c->value_int; 1942 break; 1943 1944 case LDAP_BACK_CFG_CANCEL: { 1945 slap_mask_t mask; 1946 1947 i = verb_to_mask( c->argv[1], cancel_mode ); 1948 if ( BER_BVISNULL( &cancel_mode[i].word ) ) { 1949 return 1; 1950 } 1951 1952 mask = cancel_mode[i].mask; 1953 1954 if ( LDAP_BACK_ISOPEN( li ) 1955 && mask == LDAP_BACK_F_CANCEL_EXOP_DISCOVER 1956 && !LDAP_BACK_CANCEL( li ) ) 1957 { 1958 slap_bindconf sb = { BER_BVNULL }; 1959 int rc; 1960 1961 if ( li->li_uri == NULL ) { 1962 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1963 "need URI to discover \"cancel\" support " 1964 "in \"cancel exop-discover\"" ); 1965 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1966 return 1; 1967 } 1968 1969 ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri ); 1970 sb.sb_version = li->li_version; 1971 sb.sb_method = LDAP_AUTH_SIMPLE; 1972 BER_BVSTR( &sb.sb_binddn, "" ); 1973 1974 rc = slap_discover_feature( &sb, 1975 slap_schema.si_ad_supportedExtension->ad_cname.bv_val, 1976 LDAP_EXOP_CANCEL ); 1977 if ( rc == LDAP_COMPARE_TRUE ) { 1978 mask |= LDAP_BACK_F_CANCEL_EXOP; 1979 } 1980 } 1981 1982 li->li_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 1983 li->li_flags |= mask; 1984 } break; 1985 1986 case LDAP_BACK_CFG_QUARANTINE: 1987 if ( LDAP_BACK_QUARANTINE( li ) ) { 1988 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1989 "quarantine already defined" ); 1990 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1991 return 1; 1992 } 1993 rc = slap_retry_info_parse( c->argv[1], &li->li_quarantine, 1994 c->cr_msg, sizeof( c->cr_msg ) ); 1995 if ( rc ) { 1996 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1997 1998 } else { 1999 ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex ); 2000 /* give it a chance to retry if the pattern gets reset 2001 * via back-config */ 2002 li->li_isquarantined = 0; 2003 li->li_flags |= LDAP_BACK_F_QUARANTINE; 2004 } 2005 break; 2006 2007#ifdef SLAP_CONTROL_X_SESSION_TRACKING 2008 case LDAP_BACK_CFG_ST_REQUEST: 2009 if ( c->value_int ) { 2010 li->li_flags |= LDAP_BACK_F_ST_REQUEST; 2011 2012 } else { 2013 li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; 2014 } 2015 break; 2016#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 2017 2018 case LDAP_BACK_CFG_NOREFS: 2019 if ( c->value_int ) { 2020 li->li_flags |= LDAP_BACK_F_NOREFS; 2021 2022 } else { 2023 li->li_flags &= ~LDAP_BACK_F_NOREFS; 2024 } 2025 break; 2026 2027 case LDAP_BACK_CFG_NOUNDEFFILTER: 2028 if ( c->value_int ) { 2029 li->li_flags |= LDAP_BACK_F_NOUNDEFFILTER; 2030 2031 } else { 2032 li->li_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 2033 } 2034 break; 2035 2036 case LDAP_BACK_CFG_ONERR: 2037 /* onerr? */ 2038 i = verb_to_mask( c->argv[1], onerr_mode ); 2039 if ( BER_BVISNULL( &onerr_mode[i].word ) ) { 2040 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2041 "%s unknown argument \"%s\"", 2042 c->argv[0], c->argv[1] ); 2043 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2044 return 1; 2045 } 2046 li->li_flags &= ~LDAP_BACK_F_ONERR_STOP; 2047 li->li_flags |= onerr_mode[i].mask; 2048 break; 2049 2050 case LDAP_BACK_CFG_OMIT_UNKNOWN_SCHEMA: 2051 if ( c->value_int ) { 2052 li->li_flags |= LDAP_BACK_F_OMIT_UNKNOWN_SCHEMA; 2053 2054 } else { 2055 li->li_flags &= ~LDAP_BACK_F_OMIT_UNKNOWN_SCHEMA; 2056 } 2057 break; 2058 2059 case LDAP_BACK_CFG_KEEPALIVE: 2060 slap_keepalive_parse( ber_bvstrdup(c->argv[1]), 2061 &li->li_tls.sb_keepalive, 0, 0, 0); 2062 break; 2063 2064 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 2065 li->li_tls.sb_tcp_user_timeout = c->value_uint; 2066 break; 2067 2068 default: 2069 /* FIXME: try to catch inconsistencies */ 2070 assert( 0 ); 2071 break; 2072 } 2073 2074 return rc; 2075} 2076 2077int 2078ldap_back_init_cf( BackendInfo *bi ) 2079{ 2080 int rc; 2081 2082 /* Make sure we don't exceed the bits reserved for userland */ 2083 config_check_userland( LDAP_BACK_CFG_LAST ); 2084 2085 bi->bi_cf_ocs = ldapocs; 2086 2087 rc = config_register_schema( ldapcfg, ldapocs ); 2088 if ( rc ) { 2089 return rc; 2090 } 2091 2092 return 0; 2093} 2094 2095static int 2096ldap_pbind_cf_gen( ConfigArgs *c ) 2097{ 2098 slap_overinst *on = (slap_overinst *)c->bi; 2099 void *private = c->be->be_private; 2100 int rc; 2101 2102 c->be->be_private = on->on_bi.bi_private; 2103 rc = ldap_back_cf_gen( c ); 2104 c->be->be_private = private; 2105 return rc; 2106} 2107 2108int 2109ldap_pbind_init_cf( BackendInfo *bi ) 2110{ 2111 bi->bi_cf_ocs = pbindocs; 2112 2113 return config_register_schema( pbindcfg, pbindocs ); 2114} 2115 2116static int 2117ldap_back_exop_whoami( 2118 Operation *op, 2119 SlapReply *rs ) 2120{ 2121 struct berval *bv = NULL; 2122 2123 if ( op->oq_extended.rs_reqdata != NULL ) { 2124 /* no request data should be provided */ 2125 rs->sr_text = "no request data expected"; 2126 return rs->sr_err = LDAP_PROTOCOL_ERROR; 2127 } 2128 2129 Debug( LDAP_DEBUG_STATS, "%s WHOAMI\n", 2130 op->o_log_prefix ); 2131 2132 rs->sr_err = backend_check_restrictions( op, rs, 2133 (struct berval *)&slap_EXOP_WHOAMI ); 2134 if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err; 2135 2136 /* if auth'd by back-ldap and request is proxied, forward it */ 2137 if ( op->o_conn->c_authz_backend 2138 && !strcmp( op->o_conn->c_authz_backend->be_type, "ldap" ) 2139 && !dn_match( &op->o_ndn, &op->o_conn->c_ndn ) ) 2140 { 2141 ldapconn_t *lc = NULL; 2142 LDAPControl c, *ctrls[2] = {NULL, NULL}; 2143 LDAPMessage *res; 2144 Operation op2 = *op; 2145 ber_int_t msgid; 2146 int doretry = 1; 2147 char *ptr; 2148 2149 ctrls[0] = &c; 2150 op2.o_ndn = op->o_conn->c_ndn; 2151 if ( !ldap_back_dobind( &lc, &op2, rs, LDAP_BACK_SENDERR ) ) { 2152 return -1; 2153 } 2154 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; 2155 c.ldctl_iscritical = 1; 2156 c.ldctl_value.bv_val = op->o_tmpalloc( 2157 op->o_ndn.bv_len + STRLENOF( "dn:" ) + 1, 2158 op->o_tmpmemctx ); 2159 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3; 2160 ptr = c.ldctl_value.bv_val; 2161 ptr = lutil_strcopy( ptr, "dn:" ); 2162 ptr = lutil_strncopy( ptr, op->o_ndn.bv_val, op->o_ndn.bv_len ); 2163 ptr[ 0 ] = '\0'; 2164 2165retry: 2166 rs->sr_err = ldap_whoami( lc->lc_ld, ctrls, NULL, &msgid ); 2167 if ( rs->sr_err == LDAP_SUCCESS ) { 2168 /* by now, make sure no timeout is used (ITS#6282) */ 2169 struct timeval tv = { -1, 0 }; 2170 if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { 2171 ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, 2172 &rs->sr_err ); 2173 if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) { 2174 doretry = 0; 2175 if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { 2176 goto retry; 2177 } 2178 } 2179 2180 } else { 2181 /* NOTE: are we sure "bv" will be malloc'ed 2182 * with the appropriate memory? */ 2183 rs->sr_err = ldap_parse_whoami( lc->lc_ld, res, &bv ); 2184 ldap_msgfree(res); 2185 } 2186 } 2187 op->o_tmpfree( c.ldctl_value.bv_val, op->o_tmpmemctx ); 2188 if ( rs->sr_err != LDAP_SUCCESS ) { 2189 rs->sr_err = slap_map_api2result( rs ); 2190 } 2191 2192 if ( lc != NULL ) { 2193 ldap_back_release_conn( (ldapinfo_t *)op2.o_bd->be_private, lc ); 2194 } 2195 2196 } else { 2197 /* else just do the same as before */ 2198 bv = (struct berval *) ch_malloc( sizeof( struct berval ) ); 2199 if ( !BER_BVISEMPTY( &op->o_dn ) ) { 2200 bv->bv_len = op->o_dn.bv_len + STRLENOF( "dn:" ); 2201 bv->bv_val = ch_malloc( bv->bv_len + 1 ); 2202 AC_MEMCPY( bv->bv_val, "dn:", STRLENOF( "dn:" ) ); 2203 AC_MEMCPY( &bv->bv_val[ STRLENOF( "dn:" ) ], op->o_dn.bv_val, 2204 op->o_dn.bv_len ); 2205 bv->bv_val[ bv->bv_len ] = '\0'; 2206 2207 } else { 2208 bv->bv_len = 0; 2209 bv->bv_val = NULL; 2210 } 2211 } 2212 2213 rs->sr_rspdata = bv; 2214 return rs->sr_err; 2215} 2216 2217 2218