null.c revision 1.1.1.7
1/* $NetBSD: null.c,v 1.1.1.7 2019/08/08 13:31:45 christos Exp $ */ 2 3/* null.c - the null backend */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2002-2019 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18/* ACKNOWLEDGEMENTS: 19 * This work was originally developed by Hallvard Furuseth for inclusion 20 * in OpenLDAP Software. 21 */ 22 23#include <sys/cdefs.h> 24__RCSID("$NetBSD: null.c,v 1.1.1.7 2019/08/08 13:31:45 christos Exp $"); 25 26#include "portable.h" 27 28#include <stdio.h> 29#include <ac/string.h> 30 31#include "slap.h" 32#include "config.h" 33 34typedef struct null_info { 35 int ni_bind_allowed; 36 int ni_dosearch; 37 ID ni_nextid; 38 Entry *ni_entry; 39} null_info; 40 41static ConfigTable nullcfg[] = { 42 { "bind", "true|FALSE", 1, 2, 0, ARG_ON_OFF|ARG_OFFSET, 43 (void *)offsetof(null_info, ni_bind_allowed), 44 "( OLcfgDbAt:8.1 NAME 'olcDbBindAllowed' " 45 "DESC 'Allow binds to this database' " 46 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 47 { "dosearch", "true|FALSE", 1, 2, 0, ARG_ON_OFF|ARG_OFFSET, 48 (void *)offsetof(null_info, ni_dosearch), 49 "( OLcfgDbAt:8.2 NAME 'olcDbDoSearch' " 50 "DESC 'Return an entry on searches' " 51 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 52 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 53 NULL, NULL, NULL, NULL } 54}; 55 56static ConfigOCs nullocs[] = { 57 { "( OLcfgDbOc:8.1 " 58 "NAME 'olcNullConfig' " 59 "DESC 'Null backend ocnfiguration' " 60 "SUP olcDatabaseConfig " 61 "MAY ( olcDbBindAllowed $ olcDbDoSearch ) )", 62 Cft_Database, nullcfg }, 63 { NULL, 0, NULL } 64}; 65 66 67static int 68null_back_db_open( BackendDB *be, ConfigReply *cr ) 69{ 70 struct null_info *ni = (struct null_info *) be->be_private; 71 struct berval bv[2]; 72 AttributeDescription *ad = NULL; 73 const char *text; 74 Entry *e; 75 76 if ( ni->ni_dosearch ) { 77 e = entry_alloc(); 78 e->e_name = be->be_suffix[0]; 79 e->e_nname = be->be_nsuffix[0]; 80 81 dnRdn( &e->e_nname, &bv[0] ); 82 bv[1].bv_val = strchr(bv[0].bv_val, '=') + 1; 83 bv[1].bv_len = bv[0].bv_len - (bv[1].bv_val - 84 bv[0].bv_val); 85 bv[0].bv_len -= bv[1].bv_len + 1; 86 slap_bv2ad( &bv[0], &ad, &text ); 87 attr_merge_one( e, ad, &bv[1], NULL ); 88 89 ber_str2bv("extensibleObject", 0, 0, &bv[0]); 90 attr_merge_one( e, slap_schema.si_ad_objectClass, &bv[0], NULL); 91 ni->ni_entry = e; 92 } 93 return 0; 94} 95 96/* LDAP operations */ 97 98static int 99null_back_bind( Operation *op, SlapReply *rs ) 100{ 101 struct null_info *ni = (struct null_info *) op->o_bd->be_private; 102 103 if ( ni->ni_bind_allowed || be_isroot_pw( op ) ) { 104 /* front end will send result on success (0) */ 105 return LDAP_SUCCESS; 106 } 107 108 rs->sr_err = LDAP_INVALID_CREDENTIALS; 109 send_ldap_result( op, rs ); 110 111 return rs->sr_err; 112} 113 114 115static int 116null_back_respond( Operation *op, SlapReply *rs, int rc ) 117{ 118 LDAPControl ctrl[SLAP_MAX_RESPONSE_CONTROLS], *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; 119 int c = 0; 120 121 BerElementBuffer ps_berbuf; 122 BerElement *ps_ber = NULL; 123 LDAPControl **preread_ctrl = NULL, 124 **postread_ctrl = NULL; 125 126 rs->sr_err = LDAP_OTHER; 127 128 /* this comes first, as in case of assertion failure 129 * any further processing must stop */ 130 if ( get_assert( op ) ) { 131 rs->sr_err = LDAP_ASSERTION_FAILED; 132 goto respond; 133 } 134 135 if ( op->o_preread ) { 136 Entry e = { 0 }; 137 138 switch ( op->o_tag ) { 139 case LDAP_REQ_MODIFY: 140 case LDAP_REQ_RENAME: 141 case LDAP_REQ_DELETE: 142 e.e_name = op->o_req_dn; 143 e.e_nname = op->o_req_ndn; 144 145 preread_ctrl = &ctrls[c]; 146 *preread_ctrl = NULL; 147 148 if ( slap_read_controls( op, rs, &e, 149 &slap_pre_read_bv, preread_ctrl ) ) 150 { 151 preread_ctrl = NULL; 152 153 Debug( LDAP_DEBUG_TRACE, 154 "<=- null_back_respond: pre-read " 155 "failed!\n", 0, 0, 0 ); 156 157 if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { 158 /* FIXME: is it correct to abort 159 * operation if control fails? */ 160 goto respond; 161 } 162 163 } else { 164 c++; 165 } 166 break; 167 } 168 } 169 170 if ( op->o_postread ) { 171 Entry e = { 0 }; 172 173 switch ( op->o_tag ) { 174 case LDAP_REQ_ADD: 175 case LDAP_REQ_MODIFY: 176 case LDAP_REQ_RENAME: 177 if ( op->o_tag == LDAP_REQ_ADD ) { 178 e.e_name = op->ora_e->e_name; 179 e.e_nname = op->ora_e->e_nname; 180 181 } else { 182 e.e_name = op->o_req_dn; 183 e.e_nname = op->o_req_ndn; 184 } 185 186 postread_ctrl = &ctrls[c]; 187 *postread_ctrl = NULL; 188 189 if ( slap_read_controls( op, rs, &e, 190 &slap_post_read_bv, postread_ctrl ) ) 191 { 192 postread_ctrl = NULL; 193 194 Debug( LDAP_DEBUG_TRACE, 195 "<=- null_back_respond: post-read " 196 "failed!\n", 0, 0, 0 ); 197 198 if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { 199 /* FIXME: is it correct to abort 200 * operation if control fails? */ 201 goto respond; 202 } 203 204 } else { 205 c++; 206 } 207 break; 208 } 209 } 210 211 if ( op->o_noop ) { 212 switch ( op->o_tag ) { 213 case LDAP_REQ_ADD: 214 case LDAP_REQ_MODIFY: 215 case LDAP_REQ_RENAME: 216 case LDAP_REQ_DELETE: 217 case LDAP_REQ_EXTENDED: 218 rc = LDAP_X_NO_OPERATION; 219 break; 220 } 221 } 222 223 if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { 224 struct berval cookie = BER_BVC( "" ); 225 226 /* should not be here... */ 227 assert( op->o_tag == LDAP_REQ_SEARCH ); 228 229 ctrl[c].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; 230 ctrl[c].ldctl_iscritical = 0; 231 232 ps_ber = (BerElement *)&ps_berbuf; 233 ber_init2( ps_ber, NULL, LBER_USE_DER ); 234 235 /* return size of 0 -- no estimate */ 236 ber_printf( ps_ber, "{iO}", 0, &cookie ); 237 238 if ( ber_flatten2( ps_ber, &ctrl[c].ldctl_value, 0 ) == -1 ) { 239 goto done; 240 } 241 242 ctrls[c] = &ctrl[c]; 243 c++; 244 } 245 246 /* terminate controls array */ 247 ctrls[c] = NULL; 248 rs->sr_ctrls = ctrls; 249 rs->sr_err = rc; 250 251respond:; 252 send_ldap_result( op, rs ); 253 rs->sr_ctrls = NULL; 254 255done:; 256 if ( ps_ber != NULL ) { 257 (void) ber_free_buf( ps_ber ); 258 } 259 260 if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { 261 slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); 262 slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); 263 } 264 265 if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { 266 slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); 267 slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); 268 } 269 270 return rs->sr_err; 271} 272 273/* add, delete, modify, modrdn, search */ 274static int 275null_back_success( Operation *op, SlapReply *rs ) 276{ 277 return null_back_respond( op, rs, LDAP_SUCCESS ); 278} 279 280/* compare */ 281static int 282null_back_false( Operation *op, SlapReply *rs ) 283{ 284 return null_back_respond( op, rs, LDAP_COMPARE_FALSE ); 285} 286 287static int 288null_back_search( Operation *op, SlapReply *rs ) 289{ 290 struct null_info *ni = (struct null_info *) op->o_bd->be_private; 291 292 if ( ni->ni_entry ) { 293 rs->sr_entry = ni->ni_entry; 294 rs->sr_flags = 0; 295 296 rs->sr_attrs = op->ors_attrs; 297 rs->sr_operational_attrs = NULL; 298 send_search_entry( op, rs ); 299 } 300 return null_back_respond( op, rs, LDAP_SUCCESS ); 301} 302 303/* for overlays */ 304static int 305null_back_entry_get( 306 Operation *op, 307 struct berval *ndn, 308 ObjectClass *oc, 309 AttributeDescription *at, 310 int rw, 311 Entry **ent ) 312{ 313 /* don't admit the object isn't there */ 314 return oc || at ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_BUSY; 315} 316 317static int 318null_back_entry_release( 319 Operation *op, 320 Entry *e, 321 int rw ) 322{ 323 /* we reuse our entry, don't free it */ 324 return 0; 325} 326 327/* Slap tools */ 328 329static int 330null_tool_entry_open( BackendDB *be, int mode ) 331{ 332 return 0; 333} 334 335static int 336null_tool_entry_close( BackendDB *be ) 337{ 338 assert( be != NULL ); 339 return 0; 340} 341 342static ID 343null_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f ) 344{ 345 return NOID; 346} 347 348static ID 349null_tool_entry_next( BackendDB *be ) 350{ 351 return NOID; 352} 353 354static Entry * 355null_tool_entry_get( BackendDB *be, ID id ) 356{ 357 assert( slapMode & SLAP_TOOL_MODE ); 358 return NULL; 359} 360 361static ID 362null_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) 363{ 364 assert( slapMode & SLAP_TOOL_MODE ); 365 assert( text != NULL ); 366 assert( text->bv_val != NULL ); 367 assert( text->bv_val[0] == '\0' ); /* overconservative? */ 368 369 e->e_id = ((struct null_info *) be->be_private)->ni_nextid++; 370 return e->e_id; 371} 372 373 374/* Setup */ 375 376static int 377null_back_db_init( BackendDB *be, ConfigReply *cr ) 378{ 379 struct null_info *ni = ch_calloc( 1, sizeof(struct null_info) ); 380 ni->ni_bind_allowed = 0; 381 ni->ni_nextid = 1; 382 be->be_private = ni; 383 be->be_cf_ocs = be->bd_info->bi_cf_ocs; 384 return 0; 385} 386 387static int 388null_back_db_destroy( Backend *be, ConfigReply *cr ) 389{ 390 struct null_info *ni = be->be_private; 391 392 if ( ni->ni_entry ) { 393 entry_free( ni->ni_entry ); 394 ni->ni_entry = NULL; 395 } 396 free( be->be_private ); 397 return 0; 398} 399 400 401int 402null_back_initialize( BackendInfo *bi ) 403{ 404 static char *controls[] = { 405 LDAP_CONTROL_ASSERT, 406 LDAP_CONTROL_MANAGEDSAIT, 407 LDAP_CONTROL_NOOP, 408 LDAP_CONTROL_PAGEDRESULTS, 409 LDAP_CONTROL_SUBENTRIES, 410 LDAP_CONTROL_PRE_READ, 411 LDAP_CONTROL_POST_READ, 412 LDAP_CONTROL_X_PERMISSIVE_MODIFY, 413 NULL 414 }; 415 416 Debug( LDAP_DEBUG_TRACE, 417 "null_back_initialize: initialize null backend\n", 0, 0, 0 ); 418 419 bi->bi_flags |= 420 SLAP_BFLAG_INCREMENT | 421 SLAP_BFLAG_SUBENTRIES | 422 SLAP_BFLAG_ALIASES | 423 SLAP_BFLAG_REFERRALS; 424 425 bi->bi_controls = controls; 426 427 bi->bi_open = 0; 428 bi->bi_close = 0; 429 bi->bi_config = 0; 430 bi->bi_destroy = 0; 431 432 bi->bi_db_init = null_back_db_init; 433 bi->bi_db_config = config_generic_wrapper; 434 bi->bi_db_open = null_back_db_open; 435 bi->bi_db_close = 0; 436 bi->bi_db_destroy = null_back_db_destroy; 437 438 bi->bi_op_bind = null_back_bind; 439 bi->bi_op_unbind = 0; 440 bi->bi_op_search = null_back_search; 441 bi->bi_op_compare = null_back_false; 442 bi->bi_op_modify = null_back_success; 443 bi->bi_op_modrdn = null_back_success; 444 bi->bi_op_add = null_back_success; 445 bi->bi_op_delete = null_back_success; 446 bi->bi_op_abandon = 0; 447 448 bi->bi_extended = 0; 449 450 bi->bi_chk_referrals = 0; 451 452 bi->bi_connection_init = 0; 453 bi->bi_connection_destroy = 0; 454 455 bi->bi_entry_get_rw = null_back_entry_get; 456 bi->bi_entry_release_rw = null_back_entry_release; 457 458 bi->bi_tool_entry_open = null_tool_entry_open; 459 bi->bi_tool_entry_close = null_tool_entry_close; 460 bi->bi_tool_entry_first = backend_tool_entry_first; 461 bi->bi_tool_entry_first_x = null_tool_entry_first_x; 462 bi->bi_tool_entry_next = null_tool_entry_next; 463 bi->bi_tool_entry_get = null_tool_entry_get; 464 bi->bi_tool_entry_put = null_tool_entry_put; 465 466 bi->bi_cf_ocs = nullocs; 467 return config_register_schema( nullcfg, nullocs ); 468} 469 470#if SLAPD_NULL == SLAPD_MOD_DYNAMIC 471 472/* conditionally define the init_module() function */ 473SLAP_BACKEND_INIT_MODULE( null ) 474 475#endif /* SLAPD_NULL == SLAPD_MOD_DYNAMIC */ 476