1 /*	$NetBSD: null.c,v 1.1.1.3 2010/12/12 15:23:20 adam Exp $	*/
2 
3 /* null.c - the null backend */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-null/null.c,v 1.18.2.11 2010/04/14 22:59:11 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2002-2010 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 "portable.h"
24 
25 #include <stdio.h>
26 #include <ac/string.h>
27 
28 #include "slap.h"
29 #include "config.h"
30 
31 struct null_info {
32 	int	ni_bind_allowed;
33 	ID	ni_nextid;
34 };
35 
36 
37 /* LDAP operations */
38 
39 static int
40 null_back_bind( Operation *op, SlapReply *rs )
41 {
42 	struct null_info *ni = (struct null_info *) op->o_bd->be_private;
43 
44 	if ( ni->ni_bind_allowed || be_isroot_pw( op ) ) {
45 		/* front end will send result on success (0) */
46 		return LDAP_SUCCESS;
47 	}
48 
49 	rs->sr_err = LDAP_INVALID_CREDENTIALS;
50 	send_ldap_result( op, rs );
51 
52 	return rs->sr_err;
53 }
54 
55 
56 static int
57 null_back_respond( Operation *op, SlapReply *rs, int rc )
58 {
59 	LDAPControl ctrl[SLAP_MAX_RESPONSE_CONTROLS], *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
60 	int c = 0;
61 
62 	BerElementBuffer	ps_berbuf;
63 	BerElement		*ps_ber = NULL;
64 	LDAPControl		**preread_ctrl = NULL,
65 				**postread_ctrl = NULL;
66 
67 	rs->sr_err = LDAP_OTHER;
68 
69 	/* this comes first, as in case of assertion failure
70 	 * any further processing must stop */
71 	if ( get_assert( op ) ) {
72 		rs->sr_err = LDAP_ASSERTION_FAILED;
73 		goto respond;
74 	}
75 
76 	if ( op->o_preread ) {
77 		Entry		e = { 0 };
78 
79 		switch ( op->o_tag ) {
80 		case LDAP_REQ_MODIFY:
81 		case LDAP_REQ_RENAME:
82 		case LDAP_REQ_DELETE:
83 			e.e_name = op->o_req_dn;
84 			e.e_nname = op->o_req_ndn;
85 
86 			preread_ctrl = &ctrls[c];
87 			*preread_ctrl = NULL;
88 
89 			if ( slap_read_controls( op, rs, &e,
90 				&slap_pre_read_bv, preread_ctrl ) )
91 			{
92 				preread_ctrl = NULL;
93 
94 				Debug( LDAP_DEBUG_TRACE,
95 					"<=- null_back_respond: pre-read "
96 					"failed!\n", 0, 0, 0 );
97 
98 				if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
99 					/* FIXME: is it correct to abort
100 					 * operation if control fails? */
101 					goto respond;
102 				}
103 
104 			} else {
105 				c++;
106 			}
107 			break;
108 		}
109 	}
110 
111 	if ( op->o_postread ) {
112 		Entry		e = { 0 };
113 
114 		switch ( op->o_tag ) {
115 		case LDAP_REQ_ADD:
116 		case LDAP_REQ_MODIFY:
117 		case LDAP_REQ_RENAME:
118 			if ( op->o_tag == LDAP_REQ_ADD ) {
119 				e.e_name = op->ora_e->e_name;
120 				e.e_nname = op->ora_e->e_nname;
121 
122 			} else {
123 				e.e_name = op->o_req_dn;
124 				e.e_nname = op->o_req_ndn;
125 			}
126 
127 			postread_ctrl = &ctrls[c];
128 			*postread_ctrl = NULL;
129 
130 			if ( slap_read_controls( op, rs, &e,
131 				&slap_post_read_bv, postread_ctrl ) )
132 			{
133 				postread_ctrl = NULL;
134 
135 				Debug( LDAP_DEBUG_TRACE,
136 					"<=- null_back_respond: post-read "
137 					"failed!\n", 0, 0, 0 );
138 
139 				if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
140 					/* FIXME: is it correct to abort
141 					 * operation if control fails? */
142 					goto respond;
143 				}
144 
145 			} else {
146 				c++;
147 			}
148 			break;
149 		}
150 	}
151 
152 	if ( op->o_noop ) {
153 		switch ( op->o_tag ) {
154 		case LDAP_REQ_ADD:
155 		case LDAP_REQ_MODIFY:
156 		case LDAP_REQ_RENAME:
157 		case LDAP_REQ_DELETE:
158 		case LDAP_REQ_EXTENDED:
159 			rc = LDAP_X_NO_OPERATION;
160 			break;
161 		}
162 	}
163 
164 	if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
165 		struct berval		cookie = BER_BVC( "" );
166 
167 		/* should not be here... */
168 		assert( op->o_tag == LDAP_REQ_SEARCH );
169 
170 		ctrl[c].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
171 		ctrl[c].ldctl_iscritical = 0;
172 
173 		ps_ber = (BerElement *)&ps_berbuf;
174 		ber_init2( ps_ber, NULL, LBER_USE_DER );
175 
176 		/* return size of 0 -- no estimate */
177 		ber_printf( ps_ber, "{iO}", 0, &cookie );
178 
179 		if ( ber_flatten2( ps_ber, &ctrl[c].ldctl_value, 0 ) == -1 ) {
180 			goto done;
181 		}
182 
183 		ctrls[c] = &ctrl[c];
184 		c++;
185 	}
186 
187 	/* terminate controls array */
188 	ctrls[c] = NULL;
189 	rs->sr_ctrls = ctrls;
190 	rs->sr_err = rc;
191 
192 respond:;
193 	send_ldap_result( op, rs );
194 	rs->sr_ctrls = NULL;
195 
196 done:;
197 	if ( ps_ber != NULL ) {
198 		(void) ber_free_buf( ps_ber );
199 	}
200 
201 	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
202 		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
203 		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
204 	}
205 
206 	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
207 		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
208 		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
209 	}
210 
211 	return rs->sr_err;
212 }
213 
214 /* add, delete, modify, modrdn, search */
215 static int
216 null_back_success( Operation *op, SlapReply *rs )
217 {
218 	return null_back_respond( op, rs, LDAP_SUCCESS );
219 }
220 
221 /* compare */
222 static int
223 null_back_false( Operation *op, SlapReply *rs )
224 {
225 	return null_back_respond( op, rs, LDAP_COMPARE_FALSE );
226 }
227 
228 
229 /* for overlays */
230 static int
231 null_back_entry_get(
232 	Operation *op,
233 	struct berval *ndn,
234 	ObjectClass *oc,
235 	AttributeDescription *at,
236 	int rw,
237 	Entry **ent )
238 {
239 	/* don't admit the object isn't there */
240 	return oc || at ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_BUSY;
241 }
242 
243 
244 /* Slap tools */
245 
246 static int
247 null_tool_entry_open( BackendDB *be, int mode )
248 {
249 	return 0;
250 }
251 
252 static int
253 null_tool_entry_close( BackendDB *be )
254 {
255 	assert( be != NULL );
256 	return 0;
257 }
258 
259 static ID
260 null_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
261 {
262 	return NOID;
263 }
264 
265 static ID
266 null_tool_entry_next( BackendDB *be )
267 {
268 	return NOID;
269 }
270 
271 static Entry *
272 null_tool_entry_get( BackendDB *be, ID id )
273 {
274 	assert( slapMode & SLAP_TOOL_MODE );
275 	return NULL;
276 }
277 
278 static ID
279 null_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
280 {
281 	assert( slapMode & SLAP_TOOL_MODE );
282 	assert( text != NULL );
283 	assert( text->bv_val != NULL );
284 	assert( text->bv_val[0] == '\0' );	/* overconservative? */
285 
286 	e->e_id = ((struct null_info *) be->be_private)->ni_nextid++;
287 	return e->e_id;
288 }
289 
290 
291 /* Setup */
292 
293 static int
294 null_back_db_config(
295 	BackendDB	*be,
296 	const char	*fname,
297 	int		lineno,
298 	int		argc,
299 	char		**argv )
300 {
301 	struct null_info *ni = (struct null_info *) be->be_private;
302 
303 	if ( ni == NULL ) {
304 		fprintf( stderr, "%s: line %d: null database info is null!\n",
305 			fname, lineno );
306 		return 1;
307 	}
308 
309 	/* bind requests allowed */
310 	if ( strcasecmp( argv[0], "bind" ) == 0 ) {
311 		if ( argc < 2 ) {
312 			fprintf( stderr,
313 	"%s: line %d: missing <on/off> in \"bind <on/off>\" line\n",
314 			         fname, lineno );
315 			return 1;
316 		}
317 		ni->ni_bind_allowed = strcasecmp( argv[1], "off" );
318 
319 	/* anything else */
320 	} else {
321 		return SLAP_CONF_UNKNOWN;
322 	}
323 
324 	return 0;
325 }
326 
327 static int
328 null_back_db_init( BackendDB *be, ConfigReply *cr )
329 {
330 	struct null_info *ni = ch_calloc( 1, sizeof(struct null_info) );
331 	ni->ni_bind_allowed = 0;
332 	ni->ni_nextid = 1;
333 	be->be_private = ni;
334 	return 0;
335 }
336 
337 static int
338 null_back_db_destroy( Backend *be, ConfigReply *cr )
339 {
340 	free( be->be_private );
341 	return 0;
342 }
343 
344 
345 int
346 null_back_initialize( BackendInfo *bi )
347 {
348 	static char *controls[] = {
349 		LDAP_CONTROL_ASSERT,
350 		LDAP_CONTROL_MANAGEDSAIT,
351 		LDAP_CONTROL_NOOP,
352 		LDAP_CONTROL_PAGEDRESULTS,
353 		LDAP_CONTROL_SUBENTRIES,
354 		LDAP_CONTROL_PRE_READ,
355 		LDAP_CONTROL_POST_READ,
356 		LDAP_CONTROL_X_PERMISSIVE_MODIFY,
357 		NULL
358 	};
359 
360 	Debug( LDAP_DEBUG_TRACE,
361 		"null_back_initialize: initialize null backend\n", 0, 0, 0 );
362 
363 	bi->bi_flags |=
364 		SLAP_BFLAG_INCREMENT |
365 		SLAP_BFLAG_SUBENTRIES |
366 		SLAP_BFLAG_ALIASES |
367 		SLAP_BFLAG_REFERRALS;
368 
369 	bi->bi_controls = controls;
370 
371 	bi->bi_open = 0;
372 	bi->bi_close = 0;
373 	bi->bi_config = 0;
374 	bi->bi_destroy = 0;
375 
376 	bi->bi_db_init = null_back_db_init;
377 	bi->bi_db_config = null_back_db_config;
378 	bi->bi_db_open = 0;
379 	bi->bi_db_close = 0;
380 	bi->bi_db_destroy = null_back_db_destroy;
381 
382 	bi->bi_op_bind = null_back_bind;
383 	bi->bi_op_unbind = 0;
384 	bi->bi_op_search = null_back_success;
385 	bi->bi_op_compare = null_back_false;
386 	bi->bi_op_modify = null_back_success;
387 	bi->bi_op_modrdn = null_back_success;
388 	bi->bi_op_add = null_back_success;
389 	bi->bi_op_delete = null_back_success;
390 	bi->bi_op_abandon = 0;
391 
392 	bi->bi_extended = 0;
393 
394 	bi->bi_chk_referrals = 0;
395 
396 	bi->bi_connection_init = 0;
397 	bi->bi_connection_destroy = 0;
398 
399 	bi->bi_entry_get_rw = null_back_entry_get;
400 
401 	bi->bi_tool_entry_open = null_tool_entry_open;
402 	bi->bi_tool_entry_close = null_tool_entry_close;
403 	bi->bi_tool_entry_first = backend_tool_entry_first;
404 	bi->bi_tool_entry_first_x = null_tool_entry_first_x;
405 	bi->bi_tool_entry_next = null_tool_entry_next;
406 	bi->bi_tool_entry_get = null_tool_entry_get;
407 	bi->bi_tool_entry_put = null_tool_entry_put;
408 
409 	return 0;
410 }
411 
412 #if SLAPD_NULL == SLAPD_MOD_DYNAMIC
413 
414 /* conditionally define the init_module() function */
415 SLAP_BACKEND_INIT_MODULE( null )
416 
417 #endif /* SLAPD_NULL == SLAPD_MOD_DYNAMIC */
418