config.c revision 1.1.1.3
1/*	$NetBSD: config.c,v 1.1.1.3 2010/12/12 15:23:24 adam Exp $	*/
2
3/* OpenLDAP: pkg/ldap/servers/slapd/back-sql/config.c,v 1.32.2.8 2010/04/13 20:23:42 kurt Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2010 The OpenLDAP Foundation.
7 * Portions Copyright 1999 Dmitry Kovalev.
8 * Portions Copyright 2002 Pierangelo Masarati.
9 * Portions Copyright 2004 Mark Adamson.
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 Dmitry Kovalev for inclusion
22 * by OpenLDAP Software.  Additional significant contributors include
23 * Pierangelo Masarati.
24 */
25
26#include "portable.h"
27
28#include <stdio.h>
29#include "ac/string.h"
30#include <sys/types.h>
31
32#include "slap.h"
33#include "ldif.h"
34#include "proto-sql.h"
35
36static int
37create_baseObject(
38	BackendDB	*be,
39	const char	*fname,
40	int		lineno );
41
42static int
43read_baseObject(
44	BackendDB	*be,
45	const char	*fname );
46
47int
48backsql_db_config(
49	BackendDB	*be,
50	const char	*fname,
51	int		lineno,
52	int		argc,
53	char		**argv )
54{
55	backsql_info 	*bi = (backsql_info *)be->be_private;
56
57	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_config()\n", 0, 0, 0 );
58	assert( bi != NULL );
59
60	if ( !strcasecmp( argv[ 0 ], "dbhost" ) ) {
61		if ( argc < 2 ) {
62			Debug( LDAP_DEBUG_TRACE,
63				"<==backsql_db_config (%s line %d): "
64				"missing hostname in \"dbhost\" directive\n",
65				fname, lineno, 0 );
66			return 1;
67	    	}
68		bi->sql_dbhost = ch_strdup( argv[ 1 ] );
69		Debug( LDAP_DEBUG_TRACE,
70			"<==backsql_db_config(): hostname=%s\n",
71			bi->sql_dbhost, 0, 0 );
72
73	} else if ( !strcasecmp( argv[ 0 ], "dbuser" ) ) {
74		if ( argc < 2 ) {
75			Debug( LDAP_DEBUG_TRACE,
76				"<==backsql_db_config (%s line %d): "
77				"missing username in \"dbuser\" directive\n",
78				fname, lineno, 0 );
79			return 1;
80		}
81		bi->sql_dbuser = ch_strdup( argv[ 1 ] );
82		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): dbuser=%s\n",
83			bi->sql_dbuser, 0, 0 );
84
85	} else if ( !strcasecmp( argv[ 0 ], "dbpasswd" ) ) {
86		if ( argc < 2 ) {
87			Debug( LDAP_DEBUG_TRACE,
88				"<==backsql_db_config (%s line %d): "
89				"missing password in \"dbpasswd\" directive\n",
90				fname, lineno, 0 );
91			return 1;
92		}
93		bi->sql_dbpasswd = ch_strdup( argv[ 1 ] );
94		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
95			"dbpasswd=%s\n", /* bi->sql_dbpasswd */ "xxxx", 0, 0 );
96
97	} else if ( !strcasecmp( argv[ 0 ], "dbname" ) ) {
98		if ( argc < 2 ) {
99			Debug( LDAP_DEBUG_TRACE,
100				"<==backsql_db_config (%s line %d): "
101				"missing database name in \"dbname\" "
102				"directive\n", fname, lineno, 0 );
103			return 1;
104		}
105		bi->sql_dbname = ch_strdup( argv[ 1 ] );
106		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): dbname=%s\n",
107			bi->sql_dbname, 0, 0 );
108
109	} else if ( !strcasecmp( argv[ 0 ], "concat_pattern" ) ) {
110		if ( argc < 2 ) {
111			Debug( LDAP_DEBUG_TRACE,
112				"<==backsql_db_config (%s line %d): "
113				"missing pattern"
114				"in \"concat_pattern\" directive\n",
115				fname, lineno, 0 );
116			return 1;
117		}
118		if ( backsql_split_pattern( argv[ 1 ], &bi->sql_concat_func, 2 ) ) {
119			Debug( LDAP_DEBUG_TRACE,
120				"<==backsql_db_config (%s line %d): "
121				"unable to parse pattern \"%s\"\n"
122				"in \"concat_pattern\" directive\n",
123				fname, lineno, argv[ 1 ] );
124			return 1;
125		}
126		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
127			"concat_pattern=\"%s\"\n", argv[ 1 ], 0, 0 );
128
129	} else if ( !strcasecmp( argv[ 0 ], "subtree_cond" ) ) {
130		if ( argc < 2 ) {
131			Debug( LDAP_DEBUG_TRACE,
132				"<==backsql_db_config (%s line %d): "
133				"missing SQL condition "
134				"in \"subtree_cond\" directive\n",
135				fname, lineno, 0 );
136			return 1;
137		}
138		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_subtree_cond );
139		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
140			"subtree_cond=%s\n", bi->sql_subtree_cond.bv_val, 0, 0 );
141
142	} else if ( !strcasecmp( argv[ 0 ], "children_cond" ) ) {
143		if ( argc < 2 ) {
144			Debug( LDAP_DEBUG_TRACE,
145				"<==backsql_db_config (%s line %d): "
146				"missing SQL condition "
147				"in \"children_cond\" directive\n",
148				fname, lineno, 0 );
149			return 1;
150		}
151		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_children_cond );
152		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
153			"children_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 );
154
155	} else if ( !strcasecmp( argv[ 0 ], "dn_match_cond" ) ) {
156		if ( argc < 2 ) {
157			Debug( LDAP_DEBUG_TRACE,
158				"<==backsql_db_config (%s line %d): "
159				"missing SQL condition "
160				"in \"dn_match_cond\" directive\n",
161				fname, lineno, 0 );
162			return 1;
163		}
164		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_dn_match_cond );
165		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
166			"children_cond=%s\n", bi->sql_dn_match_cond.bv_val, 0, 0 );
167
168	} else if ( !strcasecmp( argv[ 0 ], "oc_query" ) ) {
169		if ( argc < 2 ) {
170			Debug( LDAP_DEBUG_TRACE,
171				"<==backsql_db_config (%s line %d): "
172				"missing SQL statement "
173				"in \"oc_query\" directive\n",
174				fname, lineno, 0 );
175			return 1;
176		}
177		bi->sql_oc_query = ch_strdup( argv[ 1 ] );
178		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
179			"oc_query=%s\n", bi->sql_oc_query, 0, 0 );
180
181	} else if ( !strcasecmp( argv[ 0 ], "at_query" ) ) {
182		if ( argc < 2 ) {
183			Debug( LDAP_DEBUG_TRACE,
184				"<==backsql_db_config (%s line %d): "
185				"missing SQL statement "
186				"in \"at_query\" directive\n",
187				fname, lineno, 0 );
188			return 1;
189		}
190		bi->sql_at_query = ch_strdup( argv[ 1 ] );
191		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
192			"at_query=%s\n", bi->sql_at_query, 0, 0 );
193
194	} else if ( !strcasecmp( argv[ 0 ], "insentry_stmt" ) ||
195			!strcasecmp( argv[ 0 ], "insentry_query" ) )
196	{
197		if ( argc < 2 ) {
198			Debug( LDAP_DEBUG_TRACE,
199				"<==backsql_db_config (%s line %d): "
200				"missing SQL statement "
201				"in \"insentry_stmt\" directive\n",
202				fname, lineno, 0 );
203			return 1;
204		}
205		bi->sql_insentry_stmt = ch_strdup( argv[ 1 ] );
206		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
207			"insentry_stmt=%s\n", bi->sql_insentry_stmt, 0, 0 );
208
209	} else if ( !strcasecmp( argv[ 0 ], "create_needs_select" ) ) {
210		if ( argc < 2 ) {
211			Debug( LDAP_DEBUG_TRACE,
212				"<==backsql_db_config (%s line %d): "
213				"missing { yes | no }"
214				"in \"create_needs_select\" directive\n",
215				fname, lineno, 0 );
216			return 1;
217		}
218
219		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
220			bi->sql_flags |= BSQLF_CREATE_NEEDS_SELECT;
221
222		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
223			bi->sql_flags &= ~BSQLF_CREATE_NEEDS_SELECT;
224
225		} else {
226			Debug( LDAP_DEBUG_TRACE,
227				"<==backsql_db_config (%s line %d): "
228				"\"create_needs_select\" directive arg "
229				"must be \"yes\" or \"no\"\n",
230				fname, lineno, 0 );
231			return 1;
232
233		}
234		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
235			"create_needs_select =%s\n",
236			BACKSQL_CREATE_NEEDS_SELECT( bi ) ? "yes" : "no",
237			0, 0 );
238
239	} else if ( !strcasecmp( argv[ 0 ], "upper_func" ) ) {
240		if ( argc < 2 ) {
241			Debug( LDAP_DEBUG_TRACE,
242				"<==backsql_db_config (%s line %d): "
243				"missing function name "
244				"in \"upper_func\" directive\n",
245				fname, lineno, 0 );
246			return 1;
247		}
248		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_upper_func );
249		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
250			"upper_func=%s\n", bi->sql_upper_func.bv_val, 0, 0 );
251
252	} else if ( !strcasecmp( argv[ 0 ], "upper_needs_cast" ) ) {
253		if ( argc < 2 ) {
254			Debug( LDAP_DEBUG_TRACE,
255				"<==backsql_db_config (%s line %d): "
256				"missing { yes | no }"
257				"in \"upper_needs_cast\" directive\n",
258				fname, lineno, 0 );
259			return 1;
260		}
261
262		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
263			bi->sql_flags |= BSQLF_UPPER_NEEDS_CAST;
264
265		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
266			bi->sql_flags &= ~BSQLF_UPPER_NEEDS_CAST;
267
268		} else {
269			Debug( LDAP_DEBUG_TRACE,
270				"<==backsql_db_config (%s line %d): "
271				"\"upper_needs_cast\" directive arg "
272				"must be \"yes\" or \"no\"\n",
273				fname, lineno, 0 );
274			return 1;
275
276		}
277		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
278			"upper_needs_cast =%s\n",
279			BACKSQL_UPPER_NEEDS_CAST( bi ) ? "yes" : "no", 0, 0 );
280
281	} else if ( !strcasecmp( argv[ 0 ], "strcast_func" ) ) {
282		if ( argc < 2 ) {
283			Debug( LDAP_DEBUG_TRACE,
284				"<==backsql_db_config (%s line %d): "
285				"missing function name "
286				"in \"strcast_func\" directive\n",
287				fname, lineno, 0 );
288			return 1;
289		}
290		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_strcast_func );
291		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
292			"strcast_func=%s\n", bi->sql_strcast_func.bv_val, 0, 0 );
293
294	} else if ( !strcasecmp( argv[ 0 ], "delentry_stmt" ) ||
295			!strcasecmp( argv[ 0 ], "delentry_query" ) )
296	{
297		if ( argc < 2 ) {
298			Debug( LDAP_DEBUG_TRACE,
299				"<==backsql_db_config (%s line %d): "
300				"missing SQL statement "
301				"in \"delentry_stmt\" directive\n",
302				fname, lineno, 0 );
303			return 1;
304		}
305		bi->sql_delentry_stmt = ch_strdup( argv[ 1 ] );
306		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
307			"delentry_stmt=%s\n", bi->sql_delentry_stmt, 0, 0 );
308
309	} else if ( !strcasecmp( argv[ 0 ], "renentry_stmt" ) ||
310			!strcasecmp( argv[ 0 ], "renentry_query" ) )
311	{
312		if ( argc < 2 ) {
313			Debug( LDAP_DEBUG_TRACE,
314				"<==backsql_db_config (%s line %d): "
315				"missing SQL statement "
316				"in \"renentry_stmt\" directive\n",
317				fname, lineno, 0 );
318			return 1;
319		}
320		bi->sql_renentry_stmt = ch_strdup( argv[ 1 ] );
321		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
322			"renentry_stmt=%s\n", bi->sql_renentry_stmt, 0, 0 );
323
324	} else if ( !strcasecmp( argv[ 0 ], "delobjclasses_stmt" ) ||
325			!strcasecmp( argv[ 0 ], "delobjclasses_query" ) )
326	{
327		if ( argc < 2 ) {
328			Debug( LDAP_DEBUG_TRACE,
329				"<==backsql_db_config (%s line %d): "
330				"missing SQL statement "
331				"in \"delobjclasses_stmt\" directive\n",
332				fname, lineno, 0 );
333			return 1;
334		}
335		bi->sql_delobjclasses_stmt = ch_strdup( argv[ 1 ] );
336		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
337			"delobjclasses_stmt=%s\n", bi->sql_delobjclasses_stmt, 0, 0 );
338
339	} else if ( !strcasecmp( argv[ 0 ], "has_ldapinfo_dn_ru" ) ) {
340		if ( argc < 2 ) {
341			Debug( LDAP_DEBUG_TRACE,
342				"<==backsql_db_config (%s line %d): "
343				"missing { yes | no }"
344				"in \"has_ldapinfo_dn_ru\" directive\n",
345				fname, lineno, 0 );
346			return 1;
347		}
348
349		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
350			bi->sql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
351			bi->sql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
352
353		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
354			bi->sql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
355			bi->sql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
356
357		} else {
358			Debug( LDAP_DEBUG_TRACE,
359				"<==backsql_db_config (%s line %d): "
360				"\"has_ldapinfo_dn_ru\" directive arg "
361				"must be \"yes\" or \"no\"\n",
362				fname, lineno, 0 );
363			return 1;
364
365		}
366		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
367			"has_ldapinfo_dn_ru=%s\n",
368			BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ? "yes" : "no", 0, 0 );
369
370	} else if ( !strcasecmp( argv[ 0 ], "fail_if_no_mapping" ) ) {
371		if ( argc < 2 ) {
372			Debug( LDAP_DEBUG_TRACE,
373				"<==backsql_db_config (%s line %d): "
374				"missing { yes | no }"
375				"in \"fail_if_no_mapping\" directive\n",
376				fname, lineno, 0 );
377			return 1;
378		}
379
380		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
381			bi->sql_flags |= BSQLF_FAIL_IF_NO_MAPPING;
382
383		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
384			bi->sql_flags &= ~BSQLF_FAIL_IF_NO_MAPPING;
385
386		} else {
387			Debug( LDAP_DEBUG_TRACE,
388				"<==backsql_db_config (%s line %d): "
389				"\"fail_if_no_mapping\" directive arg "
390				"must be \"yes\" or \"no\"\n",
391				fname, lineno, 0 );
392			return 1;
393
394		}
395		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
396			"fail_if_no_mapping=%s\n",
397			BACKSQL_FAIL_IF_NO_MAPPING( bi ) ? "yes" : "no", 0, 0 );
398
399	} else if ( !strcasecmp( argv[ 0 ], "allow_orphans" ) ) {
400		if ( argc < 2 ) {
401			Debug( LDAP_DEBUG_TRACE,
402				"<==backsql_db_config (%s line %d): "
403				"missing { yes | no }"
404				"in \"allow_orphans\" directive\n",
405				fname, lineno, 0 );
406			return 1;
407		}
408
409		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
410			bi->sql_flags |= BSQLF_ALLOW_ORPHANS;
411
412		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
413			bi->sql_flags &= ~BSQLF_ALLOW_ORPHANS;
414
415		} else {
416			Debug( LDAP_DEBUG_TRACE,
417				"<==backsql_db_config (%s line %d): "
418				"\"allow_orphans\" directive arg "
419				"must be \"yes\" or \"no\"\n",
420				fname, lineno, 0 );
421			return 1;
422
423		}
424		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
425			"allow_orphans=%s\n",
426			BACKSQL_ALLOW_ORPHANS( bi ) ? "yes" : "no", 0, 0 );
427
428	} else if ( !strcasecmp( argv[ 0 ], "baseobject" ) ) {
429		if ( be->be_suffix == NULL ) {
430			Debug( LDAP_DEBUG_TRACE,
431				"<==backsql_db_config (%s line %d): : "
432				"must be defined after \"suffix\"\n",
433				fname, lineno, 0 );
434			return 1;
435		}
436
437		if ( bi->sql_baseObject ) {
438			Debug( LDAP_DEBUG_TRACE,
439				"<==backsql_db_config (%s line %d): : "
440				"\"baseObject\" already provided (will be overwritten)\n",
441				fname, lineno, 0 );
442			entry_free( bi->sql_baseObject );
443		}
444
445		switch ( argc ) {
446		case 1:
447			return create_baseObject( be, fname, lineno );
448
449		case 2:
450			return read_baseObject( be, argv[ 1 ] );
451
452		default:
453			Debug( LDAP_DEBUG_TRACE,
454				"<==backsql_db_config (%s line %d): "
455				"trailing values "
456				"in \"baseObject\" directive?\n",
457				fname, lineno, 0 );
458			return 1;
459		}
460
461	} else if ( !strcasecmp( argv[ 0 ], "sqllayer" ) ) {
462		if ( backsql_api_config( bi, argv[ 1 ], argc - 2, &argv[ 2 ] ) )
463		{
464			Debug( LDAP_DEBUG_TRACE,
465				"<==backsql_db_config (%s line %d): "
466				"unable to load sqllayer \"%s\"\n",
467				fname, lineno, argv[ 1 ] );
468			return 1;
469		}
470
471	} else if ( !strcasecmp( argv[ 0 ], "id_query" ) ) {
472		if ( argc < 2 ) {
473			Debug( LDAP_DEBUG_TRACE,
474				"<==backsql_db_config (%s line %d): "
475				"missing SQL condition "
476				"in \"id_query\" directive\n",
477				fname, lineno, 0 );
478			return 1;
479		}
480		bi->sql_id_query = ch_strdup( argv[ 1 ] );
481		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
482			"id_query=%s\n", bi->sql_id_query, 0, 0 );
483
484	} else if ( !strcasecmp( argv[ 0 ], "use_subtree_shortcut" ) ) {
485		if ( argc < 2 ) {
486			Debug( LDAP_DEBUG_TRACE,
487				"<==backsql_db_config (%s line %d): "
488				"missing { yes | no }"
489				"in \"use_subtree_shortcut\" directive\n",
490				fname, lineno, 0 );
491			return 1;
492		}
493
494		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
495			bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
496
497		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
498			bi->sql_flags &= ~BSQLF_USE_SUBTREE_SHORTCUT;
499
500		} else {
501			Debug( LDAP_DEBUG_TRACE,
502				"<==backsql_db_config (%s line %d): "
503				"\"use_subtree_shortcut\" directive arg "
504				"must be \"yes\" or \"no\"\n",
505				fname, lineno, 0 );
506			return 1;
507
508		}
509		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
510			"use_subtree_shortcut=%s\n",
511			BACKSQL_USE_SUBTREE_SHORTCUT( bi ) ? "yes" : "no",
512			0, 0 );
513
514	} else if ( !strcasecmp( argv[ 0 ], "fetch_all_attrs" ) ) {
515		if ( argc < 2 ) {
516			Debug( LDAP_DEBUG_TRACE,
517				"<==backsql_db_config (%s line %d): "
518				"missing { yes | no }"
519				"in \"fetch_all_attrs\" directive\n",
520				fname, lineno, 0 );
521			return 1;
522		}
523
524		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
525			bi->sql_flags |= BSQLF_FETCH_ALL_ATTRS;
526
527		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
528			bi->sql_flags &= ~BSQLF_FETCH_ALL_ATTRS;
529
530		} else {
531			Debug( LDAP_DEBUG_TRACE,
532				"<==backsql_db_config (%s line %d): "
533				"\"fetch_all_attrs\" directive arg "
534				"must be \"yes\" or \"no\"\n",
535				fname, lineno, 0 );
536			return 1;
537
538		}
539		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
540			"fetch_all_attrs=%s\n",
541			BACKSQL_FETCH_ALL_ATTRS( bi ) ? "yes" : "no",
542			0, 0 );
543
544	} else if ( !strcasecmp( argv[ 0 ], "fetch_attrs" ) ) {
545		char		*str, *s, *next;
546		const char	*delimstr = ",";
547
548		if ( argc < 2 ) {
549			Debug( LDAP_DEBUG_TRACE,
550				"<==backsql_db_config (%s line %d): "
551				"missing <attrlist>"
552				"in \"fetch_all_attrs <attrlist>\" directive\n",
553				fname, lineno, 0 );
554			return 1;
555		}
556
557		str = ch_strdup( argv[ 1 ] );
558		for ( s = ldap_pvt_strtok( str, delimstr, &next );
559				s != NULL;
560				s = ldap_pvt_strtok( NULL, delimstr, &next ) )
561		{
562			if ( strlen( s ) == 1 ) {
563				if ( *s == '*' ) {
564					bi->sql_flags |= BSQLF_FETCH_ALL_USERATTRS;
565					argv[ 1 ][ s - str ] = ',';
566
567				} else if ( *s == '+' ) {
568					bi->sql_flags |= BSQLF_FETCH_ALL_OPATTRS;
569					argv[ 1 ][ s - str ] = ',';
570				}
571			}
572		}
573		ch_free( str );
574		bi->sql_anlist = str2anlist( bi->sql_anlist, argv[ 1 ], delimstr );
575		if ( bi->sql_anlist == NULL ) {
576			return -1;
577		}
578
579	} else if ( !strcasecmp( argv[ 0 ], "check_schema" ) ) {
580		if ( argc != 2 ) {
581			Debug( LDAP_DEBUG_TRACE,
582				"<==backsql_db_config (%s line %d): "
583				"missing { yes | no }"
584				"in \"check_schema\" directive\n",
585				fname, lineno, 0 );
586			return 1;
587		}
588
589		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
590			bi->sql_flags |= BSQLF_CHECK_SCHEMA;
591
592		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
593			bi->sql_flags &= ~BSQLF_CHECK_SCHEMA;
594
595		} else {
596			Debug( LDAP_DEBUG_TRACE,
597				"<==backsql_db_config (%s line %d): "
598				"\"check_schema\" directive arg "
599				"must be \"yes\" or \"no\"\n",
600				fname, lineno, 0 );
601			return 1;
602
603		}
604		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
605			"check_schema=%s\n",
606			BACKSQL_CHECK_SCHEMA( bi ) ? "yes" : "no",
607			0, 0 );
608
609	} else if ( !strcasecmp( argv[ 0 ], "aliasing_keyword" ) ) {
610		if ( argc != 2 ) {
611			Debug( LDAP_DEBUG_TRACE,
612				"<==backsql_db_config (%s line %d): "
613				"missing arg "
614				"in \"aliasing_keyword <string>\" directive\n",
615				fname, lineno, 0 );
616			return 1;
617		}
618
619		if ( ! BER_BVISNULL( &bi->sql_aliasing ) ) {
620			ch_free( bi->sql_aliasing.bv_val );
621		}
622
623		ber_str2bv( argv[ 1 ], strlen( argv[ 1 ] ) + 1, 1,
624			&bi->sql_aliasing );
625		/* add a trailing space... */
626		bi->sql_aliasing.bv_val[ bi->sql_aliasing.bv_len - 1] = ' ';
627
628	} else if ( !strcasecmp( argv[ 0 ], "aliasing_quote" ) ) {
629		if ( argc != 2 ) {
630			Debug( LDAP_DEBUG_TRACE,
631				"<==backsql_db_config (%s line %d): "
632				"missing arg "
633				"in \"aliasing_quote <string>\" directive\n",
634				fname, lineno, 0 );
635			return 1;
636		}
637
638		if ( ! BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
639			ch_free( bi->sql_aliasing_quote.bv_val );
640		}
641
642		ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_aliasing_quote );
643
644	} else {
645		return SLAP_CONF_UNKNOWN;
646	}
647
648	return 0;
649}
650
651/*
652 * Read the entries specified in fname and merge the attributes
653 * to the user defined baseObject entry. Note that if we find any errors
654 * what so ever, we will discard the entire entries, print an
655 * error message and return.
656 */
657static int
658read_baseObject(
659	BackendDB	*be,
660	const char	*fname )
661{
662	backsql_info 	*bi = (backsql_info *)be->be_private;
663	LDIFFP		*fp;
664	int		rc = 0, lineno = 0, lmax = 0, ldifrc;
665	char		*buf = NULL;
666
667	assert( fname != NULL );
668
669	fp = ldif_open( fname, "r" );
670	if ( fp == NULL ) {
671		Debug( LDAP_DEBUG_ANY,
672			"could not open back-sql baseObject "
673			"attr file \"%s\" - absolute path?\n",
674			fname, 0, 0 );
675		perror( fname );
676		return LDAP_OTHER;
677	}
678
679	bi->sql_baseObject = entry_alloc();
680	if ( bi->sql_baseObject == NULL ) {
681		Debug( LDAP_DEBUG_ANY,
682			"read_baseObject_file: entry_alloc failed", 0, 0, 0 );
683		ldif_close( fp );
684		return LDAP_NO_MEMORY;
685	}
686	bi->sql_baseObject->e_name = be->be_suffix[0];
687	bi->sql_baseObject->e_nname = be->be_nsuffix[0];
688	bi->sql_baseObject->e_attrs = NULL;
689
690	while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) {
691		Entry		*e = str2entry( buf );
692		Attribute	*a;
693
694		if( e == NULL ) {
695			fprintf( stderr, "back-sql baseObject: "
696					"could not parse entry (line=%d)\n",
697					lineno );
698			rc = LDAP_OTHER;
699			break;
700		}
701
702		/* make sure the DN is the database's suffix */
703		if ( !be_issuffix( be, &e->e_nname ) ) {
704			fprintf( stderr,
705				"back-sql: invalid baseObject - "
706				"dn=\"%s\" (line=%d)\n",
707				e->e_name.bv_val, lineno );
708			entry_free( e );
709			rc = LDAP_OTHER;
710			break;
711		}
712
713		/*
714		 * we found a valid entry, so walk thru all the attributes in the
715		 * entry, and add each attribute type and description to baseObject
716		 */
717		for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
718			if ( attr_merge( bi->sql_baseObject, a->a_desc,
719						a->a_vals,
720						( a->a_nvals == a->a_vals ) ?
721						NULL : a->a_nvals ) )
722			{
723				rc = LDAP_OTHER;
724				break;
725			}
726		}
727
728		entry_free( e );
729		if ( rc ) {
730			break;
731		}
732	}
733
734	if ( ldifrc < 0 )
735		rc = LDAP_OTHER;
736
737	if ( rc ) {
738		entry_free( bi->sql_baseObject );
739		bi->sql_baseObject = NULL;
740	}
741
742	ch_free( buf );
743
744	ldif_close( fp );
745
746	Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n",
747			fname, 0, 0 );
748
749	return rc;
750}
751
752static int
753create_baseObject(
754	BackendDB	*be,
755	const char	*fname,
756	int		lineno )
757{
758	backsql_info 	*bi = (backsql_info *)be->be_private;
759	LDAPRDN		rdn;
760	char		*p;
761	int		rc, iAVA;
762	char		buf[1024];
763
764	snprintf( buf, sizeof(buf),
765			"dn: %s\n"
766			"objectClass: extensibleObject\n"
767			"description: builtin baseObject for back-sql\n"
768			"description: all entries mapped "
769				"in table \"ldap_entries\" "
770				"must have "
771				"\"" BACKSQL_BASEOBJECT_IDSTR "\" "
772				"in the \"parent\" column",
773			be->be_suffix[0].bv_val );
774
775	bi->sql_baseObject = str2entry( buf );
776	if ( bi->sql_baseObject == NULL ) {
777		Debug( LDAP_DEBUG_TRACE,
778			"<==backsql_db_config (%s line %d): "
779			"unable to parse baseObject entry\n",
780			fname, lineno, 0 );
781		return 1;
782	}
783
784	if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
785		return 0;
786	}
787
788	rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
789			LDAP_DN_FORMAT_LDAP );
790	if ( rc != LDAP_SUCCESS ) {
791		snprintf( buf, sizeof(buf),
792			"unable to extract RDN "
793			"from baseObject DN \"%s\" (%d: %s)",
794			be->be_suffix[ 0 ].bv_val,
795			rc, ldap_err2string( rc ) );
796		Debug( LDAP_DEBUG_TRACE,
797			"<==backsql_db_config (%s line %d): %s\n",
798			fname, lineno, buf );
799		return 1;
800	}
801
802	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
803		LDAPAVA				*ava = rdn[ iAVA ];
804		AttributeDescription		*ad = NULL;
805		slap_syntax_transform_func	*transf = NULL;
806		struct berval			bv = BER_BVNULL;
807		const char			*text = NULL;
808
809		assert( ava != NULL );
810
811		rc = slap_bv2ad( &ava->la_attr, &ad, &text );
812		if ( rc != LDAP_SUCCESS ) {
813			snprintf( buf, sizeof(buf),
814				"AttributeDescription of naming "
815				"attribute #%d from baseObject "
816				"DN \"%s\": %d: %s",
817				iAVA, be->be_suffix[ 0 ].bv_val,
818				rc, ldap_err2string( rc ) );
819			Debug( LDAP_DEBUG_TRACE,
820				"<==backsql_db_config (%s line %d): %s\n",
821				fname, lineno, buf );
822			return 1;
823		}
824
825		transf = ad->ad_type->sat_syntax->ssyn_pretty;
826		if ( transf ) {
827			/*
828	 		 * transform value by pretty function
829			 *	if value is empty, use empty_bv
830			 */
831			rc = ( *transf )( ad->ad_type->sat_syntax,
832				ava->la_value.bv_len
833					? &ava->la_value
834					: (struct berval *) &slap_empty_bv,
835				&bv, NULL );
836
837			if ( rc != LDAP_SUCCESS ) {
838				snprintf( buf, sizeof(buf),
839					"prettying of attribute #%d "
840					"from baseObject "
841					"DN \"%s\" failed: %d: %s",
842					iAVA, be->be_suffix[ 0 ].bv_val,
843					rc, ldap_err2string( rc ) );
844				Debug( LDAP_DEBUG_TRACE,
845					"<==backsql_db_config (%s line %d): "
846					"%s\n",
847					fname, lineno, buf );
848				return 1;
849			}
850		}
851
852		if ( !BER_BVISNULL( &bv ) ) {
853			if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
854				ber_memfree( ava->la_value.bv_val );
855			}
856			ava->la_value = bv;
857			ava->la_flags |= LDAP_AVA_FREE_VALUE;
858		}
859
860		attr_merge_normalize_one( bi->sql_baseObject,
861				ad, &ava->la_value, NULL );
862	}
863
864	ldap_rdnfree( rdn );
865
866	return 0;
867}
868
869