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