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