1 /* $NetBSD: entry-id.c,v 1.3 2021/08/14 16:15:01 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2021 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 and Mark Adamson.
24 */
25
26 #include <sys/cdefs.h>
27 __RCSID("$NetBSD: entry-id.c,v 1.3 2021/08/14 16:15:01 christos Exp $");
28
29 #include "portable.h"
30
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include "ac/string.h"
34
35 #include "lutil.h"
36 #include "slap.h"
37 #include "proto-sql.h"
38
39 #ifdef BACKSQL_ARBITRARY_KEY
40 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
41 #endif /* BACKSQL_ARBITRARY_KEY */
42
43 backsql_entryID *
backsql_entryID_dup(backsql_entryID * src,void * ctx)44 backsql_entryID_dup( backsql_entryID *src, void *ctx )
45 {
46 backsql_entryID *dst;
47
48 if ( src == NULL ) return NULL;
49
50 dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
51 ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
52 if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
53 dst->eid_dn = dst->eid_ndn;
54 } else {
55 ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
56 }
57
58 #ifdef BACKSQL_ARBITRARY_KEY
59 ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
60 ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
61 #else /* ! BACKSQL_ARBITRARY_KEY */
62 dst->eid_id = src->eid_id;
63 dst->eid_keyval = src->eid_keyval;
64 #endif /* ! BACKSQL_ARBITRARY_KEY */
65
66 dst->eid_oc = src->eid_oc;
67 dst->eid_oc_id = src->eid_oc_id;
68
69 return dst;
70 }
71
72 backsql_entryID *
backsql_free_entryID(backsql_entryID * id,int freeit,void * ctx)73 backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
74 {
75 backsql_entryID *next;
76
77 assert( id != NULL );
78
79 next = id->eid_next;
80
81 if ( !BER_BVISNULL( &id->eid_ndn ) ) {
82 if ( !BER_BVISNULL( &id->eid_dn )
83 && id->eid_dn.bv_val != id->eid_ndn.bv_val )
84 {
85 slap_sl_free( id->eid_dn.bv_val, ctx );
86 BER_BVZERO( &id->eid_dn );
87 }
88
89 slap_sl_free( id->eid_ndn.bv_val, ctx );
90 BER_BVZERO( &id->eid_ndn );
91 }
92
93 #ifdef BACKSQL_ARBITRARY_KEY
94 if ( !BER_BVISNULL( &id->eid_id ) ) {
95 slap_sl_free( id->eid_id.bv_val, ctx );
96 BER_BVZERO( &id->eid_id );
97 }
98
99 if ( !BER_BVISNULL( &id->eid_keyval ) ) {
100 slap_sl_free( id->eid_keyval.bv_val, ctx );
101 BER_BVZERO( &id->eid_keyval );
102 }
103 #endif /* BACKSQL_ARBITRARY_KEY */
104
105 if ( freeit ) {
106 slap_sl_free( id, ctx );
107 }
108
109 return next;
110 }
111
112 /*
113 * NOTE: the dn must be normalized
114 */
115 int
backsql_dn2id(Operation * op,SlapReply * rs,SQLHDBC dbh,struct berval * ndn,backsql_entryID * id,int matched,int muck)116 backsql_dn2id(
117 Operation *op,
118 SlapReply *rs,
119 SQLHDBC dbh,
120 struct berval *ndn,
121 backsql_entryID *id,
122 int matched,
123 int muck )
124 {
125 backsql_info *bi = op->o_bd->be_private;
126 SQLHSTMT sth = SQL_NULL_HSTMT;
127 BACKSQL_ROW_NTS row = { 0 };
128 RETCODE rc;
129 int res;
130 struct berval realndn = BER_BVNULL;
131
132 /* TimesTen */
133 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
134 struct berval tbbDN;
135 int i, j;
136
137 /*
138 * NOTE: id can be NULL; in this case, the function
139 * simply checks whether the DN can be successfully
140 * turned into an ID, returning LDAP_SUCCESS for
141 * positive cases, or the most appropriate error
142 */
143
144 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n",
145 ndn->bv_val, id == NULL ? " (no ID expected)" : "",
146 matched ? " matched expected" : "" );
147
148 if ( id ) {
149 /* NOTE: trap inconsistencies */
150 assert( BER_BVISNULL( &id->eid_ndn ) );
151 }
152
153 if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
154 Debug( LDAP_DEBUG_TRACE,
155 " backsql_dn2id(\"%s\"): DN length=%ld "
156 "exceeds max DN length %d:\n",
157 ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
158 return LDAP_OTHER;
159 }
160
161 /* return baseObject if available and matches */
162 /* FIXME: if ndn is already mucked, we cannot check this */
163 if ( bi->sql_baseObject != NULL &&
164 dn_match( ndn, &bi->sql_baseObject->e_nname ) )
165 {
166 if ( id != NULL ) {
167 #ifdef BACKSQL_ARBITRARY_KEY
168 ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv,
169 op->o_tmpmemctx );
170 ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv,
171 op->o_tmpmemctx );
172 #else /* ! BACKSQL_ARBITRARY_KEY */
173 id->eid_id = BACKSQL_BASEOBJECT_ID;
174 id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
175 #endif /* ! BACKSQL_ARBITRARY_KEY */
176 id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
177
178 ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname,
179 op->o_tmpmemctx );
180 ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name,
181 op->o_tmpmemctx );
182
183 id->eid_next = NULL;
184 }
185
186 return LDAP_SUCCESS;
187 }
188
189 /* begin TimesTen */
190 assert( bi->sql_id_query != NULL );
191 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): id_query \"%s\"\n",
192 ndn->bv_val, bi->sql_id_query );
193 rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
194 if ( rc != SQL_SUCCESS ) {
195 Debug( LDAP_DEBUG_TRACE,
196 " backsql_dn2id(\"%s\"): "
197 "error preparing SQL:\n %s",
198 ndn->bv_val, bi->sql_id_query );
199 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
200 res = LDAP_OTHER;
201 goto done;
202 }
203
204 realndn = *ndn;
205 if ( muck ) {
206 if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
207 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
208 "backsql_api_dn2odbc(\"%s\") failed\n",
209 ndn->bv_val, realndn.bv_val );
210 res = LDAP_OTHER;
211 goto done;
212 }
213 }
214
215 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
216 /*
217 * Prepare an upper cased, byte reversed version
218 * that can be searched using indexes
219 */
220
221 for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
222 {
223 upperdn[ i ] = realndn.bv_val[ j ];
224 }
225 upperdn[ i ] = '\0';
226 ldap_pvt_str2upper( upperdn );
227
228 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
229 "upperdn=\"%s\"\n",
230 ndn->bv_val, upperdn );
231 ber_str2bv( upperdn, 0, 0, &tbbDN );
232
233 } else {
234 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
235 AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
236 ldap_pvt_str2upper( upperdn );
237 Debug( LDAP_DEBUG_TRACE,
238 " backsql_dn2id(\"%s\"): "
239 "upperdn=\"%s\"\n",
240 ndn->bv_val, upperdn );
241 ber_str2bv( upperdn, 0, 0, &tbbDN );
242
243 } else {
244 tbbDN = realndn;
245 }
246 }
247
248 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
249 if ( rc != SQL_SUCCESS) {
250 /* end TimesTen */
251 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
252 "error binding dn=\"%s\" parameter:\n",
253 ndn->bv_val, tbbDN.bv_val );
254 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
255 res = LDAP_OTHER;
256 goto done;
257 }
258
259 rc = SQLExecute( sth );
260 if ( rc != SQL_SUCCESS ) {
261 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
262 "error executing query (\"%s\", \"%s\"):\n",
263 ndn->bv_val, bi->sql_id_query, tbbDN.bv_val );
264 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
265 res = LDAP_OTHER;
266 goto done;
267 }
268
269 backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
270 rc = SQLFetch( sth );
271 if ( BACKSQL_SUCCESS( rc ) ) {
272 #ifdef LDAP_DEBUG
273 Debug(LDAP_DEBUG_TRACE,
274 " backsql_dn2id(\"%s\"): id=%s keyval=%s oc_id=%s dn=%s\n",
275 ndn->bv_val, row.cols[0], row.cols[1], row.cols[2],
276 row.cols[3] );
277 #endif /* LDAP_DEBUG */
278
279 res = LDAP_SUCCESS;
280 if ( id != NULL ) {
281 struct berval dn;
282
283 id->eid_next = NULL;
284
285 #ifdef BACKSQL_ARBITRARY_KEY
286 ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id,
287 op->o_tmpmemctx );
288 ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval,
289 op->o_tmpmemctx );
290 #else /* ! BACKSQL_ARBITRARY_KEY */
291 if ( BACKSQL_STR2ID( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) {
292 res = LDAP_OTHER;
293 goto done;
294 }
295 if ( BACKSQL_STR2ID( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) {
296 res = LDAP_OTHER;
297 goto done;
298 }
299 #endif /* ! BACKSQL_ARBITRARY_KEY */
300 if ( BACKSQL_STR2ID( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) {
301 res = LDAP_OTHER;
302 goto done;
303 }
304
305 ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
306
307 if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
308 res = LDAP_OTHER;
309 goto done;
310 }
311
312 res = dnPrettyNormal( NULL, &dn,
313 &id->eid_dn, &id->eid_ndn,
314 op->o_tmpmemctx );
315 if ( res != LDAP_SUCCESS ) {
316 Debug( LDAP_DEBUG_TRACE,
317 " backsql_dn2id(\"%s\"): "
318 "dnPrettyNormal failed (%d: %s)\n",
319 realndn.bv_val, res,
320 ldap_err2string( res ) );
321
322 /* cleanup... */
323 (void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
324 }
325
326 if ( dn.bv_val != row.cols[ 3 ] ) {
327 free( dn.bv_val );
328 }
329 }
330
331 } else {
332 res = LDAP_NO_SUCH_OBJECT;
333 if ( matched ) {
334 struct berval pdn = *ndn;
335
336 /*
337 * Look for matched
338 */
339 rs->sr_matched = NULL;
340 while ( !be_issuffix( op->o_bd, &pdn ) ) {
341 char *matchedDN = NULL;
342
343 dnParent( &pdn, &pdn );
344
345 /*
346 * Empty DN ("") defaults to LDAP_SUCCESS
347 */
348 rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 );
349 switch ( rs->sr_err ) {
350 case LDAP_NO_SUCH_OBJECT:
351 /* try another one */
352 break;
353
354 case LDAP_SUCCESS:
355 matchedDN = pdn.bv_val;
356 /* fail over to next case */
357
358 default:
359 rs->sr_err = LDAP_NO_SUCH_OBJECT;
360 rs->sr_matched = matchedDN;
361 goto done;
362 }
363 }
364 }
365 }
366
367 done:;
368 backsql_FreeRow_x( &row, op->o_tmpmemctx );
369
370 Debug( LDAP_DEBUG_TRACE,
371 "<==backsql_dn2id(\"%s\"): err=%d\n",
372 ndn->bv_val, res );
373 if ( sth != SQL_NULL_HSTMT ) {
374 SQLFreeStmt( sth, SQL_DROP );
375 }
376
377 if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
378 ch_free( realndn.bv_val );
379 }
380
381 return res;
382 }
383
384 int
backsql_count_children(Operation * op,SQLHDBC dbh,struct berval * dn,unsigned long * nchildren)385 backsql_count_children(
386 Operation *op,
387 SQLHDBC dbh,
388 struct berval *dn,
389 unsigned long *nchildren )
390 {
391 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
392 SQLHSTMT sth = SQL_NULL_HSTMT;
393 BACKSQL_ROW_NTS row;
394 RETCODE rc;
395 int res = LDAP_SUCCESS;
396
397 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
398 dn->bv_val );
399
400 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
401 Debug( LDAP_DEBUG_TRACE,
402 "backsql_count_children(): DN \"%s\" (%ld bytes) "
403 "exceeds max DN length (%d):\n",
404 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
405 return LDAP_OTHER;
406 }
407
408 /* begin TimesTen */
409 assert( bi->sql_has_children_query != NULL );
410 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
411 bi->sql_has_children_query );
412 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
413 if ( rc != SQL_SUCCESS ) {
414 Debug( LDAP_DEBUG_TRACE,
415 "backsql_count_children(): error preparing SQL:\n%s",
416 bi->sql_has_children_query );
417 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
418 SQLFreeStmt( sth, SQL_DROP );
419 return LDAP_OTHER;
420 }
421
422 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
423 if ( rc != SQL_SUCCESS) {
424 /* end TimesTen */
425 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
426 "error binding dn=\"%s\" parameter:\n",
427 dn->bv_val );
428 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
429 SQLFreeStmt( sth, SQL_DROP );
430 return LDAP_OTHER;
431 }
432
433 rc = SQLExecute( sth );
434 if ( rc != SQL_SUCCESS ) {
435 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
436 "error executing query (\"%s\", \"%s\"):\n",
437 bi->sql_has_children_query, dn->bv_val );
438 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
439 SQLFreeStmt( sth, SQL_DROP );
440 return LDAP_OTHER;
441 }
442
443 backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
444
445 rc = SQLFetch( sth );
446 if ( BACKSQL_SUCCESS( rc ) ) {
447 char *end;
448
449 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
450 if ( end == row.cols[ 0 ] ) {
451 res = LDAP_OTHER;
452
453 } else {
454 switch ( end[ 0 ] ) {
455 case '\0':
456 break;
457
458 case '.': {
459 unsigned long ul;
460
461 /* FIXME: braindead RDBMSes return
462 * a fractional number from COUNT!
463 */
464 if ( lutil_atoul( &ul, end + 1 ) != 0 || ul != 0 ) {
465 res = LDAP_OTHER;
466 }
467 } break;
468
469 default:
470 res = LDAP_OTHER;
471 }
472 }
473
474 } else {
475 res = LDAP_OTHER;
476 }
477 backsql_FreeRow_x( &row, op->o_tmpmemctx );
478
479 SQLFreeStmt( sth, SQL_DROP );
480
481 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
482 *nchildren );
483
484 return res;
485 }
486
487 int
backsql_has_children(Operation * op,SQLHDBC dbh,struct berval * dn)488 backsql_has_children(
489 Operation *op,
490 SQLHDBC dbh,
491 struct berval *dn )
492 {
493 unsigned long nchildren;
494 int rc;
495
496 rc = backsql_count_children( op, dbh, dn, &nchildren );
497
498 if ( rc == LDAP_SUCCESS ) {
499 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
500 }
501
502 return rc;
503 }
504
505 static int
backsql_get_attr_vals(void * v_at,void * v_bsi)506 backsql_get_attr_vals( void *v_at, void *v_bsi )
507 {
508 backsql_at_map_rec *at = v_at;
509 backsql_srch_info *bsi = v_bsi;
510 backsql_info *bi;
511 RETCODE rc;
512 SQLHSTMT sth = SQL_NULL_HSTMT;
513 BACKSQL_ROW_NTS row;
514 unsigned long i,
515 k = 0,
516 oldcount = 0,
517 res = 0;
518 #ifdef BACKSQL_COUNTQUERY
519 unsigned count,
520 j,
521 append = 0;
522 SQLLEN countsize = sizeof( count );
523 Attribute *attr = NULL;
524
525 slap_mr_normalize_func *normfunc = NULL;
526 #endif /* BACKSQL_COUNTQUERY */
527 #ifdef BACKSQL_PRETTY_VALIDATE
528 slap_syntax_validate_func *validate = NULL;
529 slap_syntax_transform_func *pretty = NULL;
530 #endif /* BACKSQL_PRETTY_VALIDATE */
531
532 assert( at != NULL );
533 assert( bsi != NULL );
534 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
535 "oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n",
536 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
537 BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) );
538
539 bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
540
541 #ifdef BACKSQL_PRETTY_VALIDATE
542 validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
543 pretty = at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
544
545 if ( validate == NULL && pretty == NULL ) {
546 return 1;
547 }
548 #endif /* BACKSQL_PRETTY_VALIDATE */
549
550 #ifdef BACKSQL_COUNTQUERY
551 if ( at->bam_true_ad->ad_type->sat_equality ) {
552 normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
553 }
554
555 /* Count how many rows will be returned. This avoids memory
556 * fragmentation that can result from loading the values in
557 * one by one and using realloc()
558 */
559 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 );
560 if ( rc != SQL_SUCCESS ) {
561 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
562 "error preparing count query: %s\n",
563 at->bam_countquery );
564 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
565 return 1;
566 }
567
568 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
569 &bsi->bsi_c_eid->eid_keyval );
570 if ( rc != SQL_SUCCESS ) {
571 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
572 "error binding key value parameter\n" );
573 SQLFreeStmt( sth, SQL_DROP );
574 return 1;
575 }
576
577 rc = SQLExecute( sth );
578 if ( ! BACKSQL_SUCCESS( rc ) ) {
579 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
580 "error executing attribute count query '%s'\n",
581 at->bam_countquery );
582 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
583 SQLFreeStmt( sth, SQL_DROP );
584 return 1;
585 }
586
587 SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG,
588 (SQLPOINTER)&count,
589 (SQLINTEGER)sizeof( count ),
590 &countsize );
591
592 rc = SQLFetch( sth );
593 if ( rc != SQL_SUCCESS ) {
594 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
595 "error fetch results of count query: %s\n",
596 at->bam_countquery );
597 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
598 SQLFreeStmt( sth, SQL_DROP );
599 return 1;
600 }
601
602 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
603 "number of values in query: %u\n", count );
604 SQLFreeStmt( sth, SQL_DROP );
605 if ( count == 0 ) {
606 return 1;
607 }
608
609 attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
610 if ( attr != NULL ) {
611 BerVarray tmp;
612
613 if ( attr->a_vals != NULL ) {
614 oldcount = attr->a_numvals;
615 }
616
617 tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
618 if ( tmp == NULL ) {
619 return 1;
620 }
621 attr->a_vals = tmp;
622 memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
623
624 if ( normfunc ) {
625 tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
626 if ( tmp == NULL ) {
627 return 1;
628 }
629 attr->a_nvals = tmp;
630 memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
631
632 } else {
633 attr->a_nvals = attr->a_vals;
634 }
635 attr->a_numvals += count;
636
637 } else {
638 append = 1;
639
640 /* Make space for the array of values */
641 attr = attr_alloc( at->bam_true_ad );
642 attr->a_numvals = count;
643 attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
644 if ( attr->a_vals == NULL ) {
645 Debug( LDAP_DEBUG_TRACE, "Out of memory!\n" );
646 ch_free( attr );
647 return 1;
648 }
649 if ( normfunc ) {
650 attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
651 if ( attr->a_nvals == NULL ) {
652 ch_free( attr->a_vals );
653 ch_free( attr );
654 return 1;
655
656 }
657
658 } else {
659 attr->a_nvals = attr->a_vals;
660 }
661 }
662 #endif /* BACKSQL_COUNTQUERY */
663
664 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
665 if ( rc != SQL_SUCCESS ) {
666 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
667 "error preparing query: %s\n", at->bam_query );
668 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
669 #ifdef BACKSQL_COUNTQUERY
670 if ( append ) {
671 attr_free( attr );
672 }
673 #endif /* BACKSQL_COUNTQUERY */
674 return 1;
675 }
676
677 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
678 &bsi->bsi_c_eid->eid_keyval );
679 if ( rc != SQL_SUCCESS ) {
680 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
681 "error binding key value parameter\n" );
682 #ifdef BACKSQL_COUNTQUERY
683 if ( append ) {
684 attr_free( attr );
685 }
686 #endif /* BACKSQL_COUNTQUERY */
687 return 1;
688 }
689
690 #ifdef BACKSQL_TRACE
691 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
692 "query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query,
693 BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) );
694 #endif /* BACKSQL_TRACE */
695
696 rc = SQLExecute( sth );
697 if ( ! BACKSQL_SUCCESS( rc ) ) {
698 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
699 "error executing attribute query \"%s\"\n",
700 at->bam_query );
701 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
702 SQLFreeStmt( sth, SQL_DROP );
703 #ifdef BACKSQL_COUNTQUERY
704 if ( append ) {
705 attr_free( attr );
706 }
707 #endif /* BACKSQL_COUNTQUERY */
708 return 1;
709 }
710
711 backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx );
712 #ifdef BACKSQL_COUNTQUERY
713 j = oldcount;
714 #endif /* BACKSQL_COUNTQUERY */
715 for ( rc = SQLFetch( sth ), k = 0;
716 BACKSQL_SUCCESS( rc );
717 rc = SQLFetch( sth ), k++ )
718 {
719 for ( i = 0; i < (unsigned long)row.ncols; i++ ) {
720
721 if ( row.value_len[ i ] > 0 ) {
722 struct berval bv;
723 int retval;
724 #ifdef BACKSQL_TRACE
725 AttributeDescription *ad = NULL;
726 const char *text;
727
728 retval = slap_bv2ad( &row.col_names[ i ], &ad, &text );
729 if ( retval != LDAP_SUCCESS ) {
730 Debug( LDAP_DEBUG_ANY,
731 "==>backsql_get_attr_vals(\"%s\"): "
732 "unable to find AttributeDescription %s "
733 "in schema (%d)\n",
734 bsi->bsi_e->e_name.bv_val,
735 row.col_names[ i ].bv_val, retval );
736 res = 1;
737 goto done;
738 }
739
740 if ( ad != at->bam_ad ) {
741 Debug( LDAP_DEBUG_ANY,
742 "==>backsql_get_attr_vals(\"%s\"): "
743 "column name %s differs from "
744 "AttributeDescription %s\n",
745 bsi->bsi_e->e_name.bv_val,
746 ad->ad_cname.bv_val,
747 at->bam_ad->ad_cname.bv_val );
748 res = 1;
749 goto done;
750 }
751 #endif /* BACKSQL_TRACE */
752
753 /* ITS#3386, ITS#3113 - 20070308
754 * If a binary is fetched?
755 * must use the actual size read
756 * from the database.
757 */
758 if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
759 #ifdef BACKSQL_TRACE
760 Debug( LDAP_DEBUG_ANY,
761 "==>backsql_get_attr_vals(\"%s\"): "
762 "column name %s: data is binary; "
763 "using database size %ld\n",
764 bsi->bsi_e->e_name.bv_val,
765 ad->ad_cname.bv_val,
766 row.value_len[ i ] );
767 #endif /* BACKSQL_TRACE */
768 bv.bv_val = row.cols[ i ];
769 bv.bv_len = row.value_len[ i ];
770
771 } else {
772 ber_str2bv( row.cols[ i ], 0, 0, &bv );
773 }
774
775 #ifdef BACKSQL_PRETTY_VALIDATE
776 if ( pretty ) {
777 struct berval pbv;
778
779 retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
780 &bv, &pbv, bsi->bsi_op->o_tmpmemctx );
781 bv = pbv;
782
783 } else {
784 retval = validate( at->bam_true_ad->ad_type->sat_syntax,
785 &bv );
786 }
787
788 if ( retval != LDAP_SUCCESS ) {
789 /* FIXME: we're ignoring invalid values,
790 * but we're accepting the attributes;
791 * should we fail at all? */
792 Debug(LDAP_DEBUG_TRACE,
793 "==>backsql_get_attr_vals(\"%s\"): " "unable to %s value #%lu " "of AttributeDescription %s (%d)\n",
794 bsi->bsi_e->e_name.bv_val,
795 pretty ? "prettify" : "validate",
796 k - oldcount,
797 at->bam_ad->ad_cname.bv_val,
798 retval );
799 continue;
800 }
801 #endif /* BACKSQL_PRETTY_VALIDATE */
802
803 #ifndef BACKSQL_COUNTQUERY
804 (void)backsql_entry_addattr( bsi->bsi_e,
805 at->bam_true_ad, &bv,
806 bsi->bsi_op->o_tmpmemctx );
807
808 #else /* BACKSQL_COUNTQUERY */
809 if ( normfunc ) {
810 struct berval nbv;
811
812 retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
813 at->bam_true_ad->ad_type->sat_syntax,
814 at->bam_true_ad->ad_type->sat_equality,
815 &bv, &nbv,
816 bsi->bsi_op->o_tmpmemctx );
817
818 if ( retval != LDAP_SUCCESS ) {
819 /* FIXME: we're ignoring invalid values,
820 * but we're accepting the attributes;
821 * should we fail at all? */
822 Debug(LDAP_DEBUG_TRACE,
823 "==>backsql_get_attr_vals(\"%s\"): " "unable to normalize value #%lu " "of AttributeDescription %s (%d)\n",
824 bsi->bsi_e->e_name.bv_val,
825 k - oldcount,
826 at->bam_ad->ad_cname.bv_val,
827 retval );
828
829 #ifdef BACKSQL_PRETTY_VALIDATE
830 if ( pretty ) {
831 bsi->bsi_op->o_tmpfree( bv.bv_val,
832 bsi->bsi_op->o_tmpmemctx );
833 }
834 #endif /* BACKSQL_PRETTY_VALIDATE */
835
836 continue;
837 }
838 ber_dupbv( &attr->a_nvals[ j ], &nbv );
839 bsi->bsi_op->o_tmpfree( nbv.bv_val,
840 bsi->bsi_op->o_tmpmemctx );
841 }
842
843 ber_dupbv( &attr->a_vals[ j ], &bv );
844
845 assert( j < oldcount + count );
846 j++;
847 #endif /* BACKSQL_COUNTQUERY */
848
849 #ifdef BACKSQL_PRETTY_VALIDATE
850 if ( pretty ) {
851 bsi->bsi_op->o_tmpfree( bv.bv_val,
852 bsi->bsi_op->o_tmpmemctx );
853 }
854 #endif /* BACKSQL_PRETTY_VALIDATE */
855
856 #ifdef BACKSQL_TRACE
857 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
858 (int)row.col_prec[ i ] );
859
860 } else {
861 Debug( LDAP_DEBUG_TRACE, "NULL value "
862 "in this row for attribute \"%s\"\n",
863 row.col_names[ i ].bv_val );
864 #endif /* BACKSQL_TRACE */
865 }
866 }
867 }
868
869 #ifdef BACKSQL_COUNTQUERY
870 if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) {
871 /* don't leave around attributes with no values */
872 attr_free( attr );
873
874 } else if ( append ) {
875 Attribute **ap;
876
877 for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next )
878 /* goto last */ ;
879 *ap = attr;
880 }
881 #endif /* BACKSQL_COUNTQUERY */
882
883 SQLFreeStmt( sth, SQL_DROP );
884 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n" );
885
886 if ( at->bam_next ) {
887 res = backsql_get_attr_vals( at->bam_next, v_bsi );
888 } else {
889 res = 1;
890 }
891
892 #ifdef BACKSQL_TRACE
893 done:;
894 #endif /* BACKSQL_TRACE */
895 backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx );
896
897 return res;
898 }
899
900 int
backsql_id2entry(backsql_srch_info * bsi,backsql_entryID * eid)901 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
902 {
903 Operation *op = bsi->bsi_op;
904 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
905 int i;
906 int rc;
907
908 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n" );
909
910 assert( bsi->bsi_e != NULL );
911
912 memset( bsi->bsi_e, 0, sizeof( Entry ) );
913
914 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
915 (void)entry_dup2( bsi->bsi_e, bi->sql_baseObject );
916 goto done;
917 }
918
919 bsi->bsi_e->e_attrs = NULL;
920 bsi->bsi_e->e_private = NULL;
921
922 if ( eid->eid_oc == NULL ) {
923 eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
924 eid->eid_oc_id );
925 if ( eid->eid_oc == NULL ) {
926 Debug( LDAP_DEBUG_TRACE,
927 "backsql_id2entry(): unable to fetch objectClass with id=" BACKSQL_IDNUMFMT " for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n",
928 eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id),
929 eid->eid_dn.bv_val );
930 return LDAP_OTHER;
931 }
932 }
933 bsi->bsi_oc = eid->eid_oc;
934 bsi->bsi_c_eid = eid;
935
936 ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
937 ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );
938
939 #ifndef BACKSQL_ARBITRARY_KEY
940 /* FIXME: unused */
941 bsi->bsi_e->e_id = eid->eid_id;
942 #endif /* ! BACKSQL_ARBITRARY_KEY */
943
944 rc = attr_merge_normalize_one( bsi->bsi_e,
945 slap_schema.si_ad_objectClass,
946 &bsi->bsi_oc->bom_oc->soc_cname,
947 bsi->bsi_op->o_tmpmemctx );
948 if ( rc != LDAP_SUCCESS ) {
949 backsql_entry_clean( op, bsi->bsi_e );
950 return rc;
951 }
952
953 if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
954 {
955 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
956 "retrieving all attributes\n" );
957 ldap_avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
958 bsi, 0, AVL_INORDER );
959
960 } else {
961 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
962 "custom attribute list\n" );
963 for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
964 backsql_at_map_rec **vat;
965 AttributeName *an = &bsi->bsi_attrs[ i ];
966 int j;
967
968 /* if one of the attributes listed here is
969 * a subtype of another, it must be ignored,
970 * because subtypes are already dealt with
971 * by backsql_supad2at()
972 */
973 for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
974 /* skip self */
975 if ( j == i ) {
976 continue;
977 }
978
979 /* skip subtypes */
980 if ( is_at_subtype( an->an_desc->ad_type,
981 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
982 {
983 goto next;
984 }
985 }
986
987 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
988 if ( rc != 0 || vat == NULL ) {
989 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
990 "attribute \"%s\" is not defined "
991 "for objectclass \"%s\"\n",
992 an->an_name.bv_val,
993 BACKSQL_OC_NAME( bsi->bsi_oc ) );
994 continue;
995 }
996
997 for ( j = 0; vat[j]; j++ ) {
998 backsql_get_attr_vals( vat[j], bsi );
999 }
1000
1001 ch_free( vat );
1002
1003 next:;
1004 }
1005 }
1006
1007 if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
1008 Attribute *a_entryUUID,
1009 **ap;
1010
1011 a_entryUUID = backsql_operational_entryUUID( bi, eid );
1012 if ( a_entryUUID != NULL ) {
1013 for ( ap = &bsi->bsi_e->e_attrs;
1014 *ap;
1015 ap = &(*ap)->a_next );
1016
1017 *ap = a_entryUUID;
1018 }
1019 }
1020
1021 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
1022 || an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs )
1023 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
1024 {
1025 ObjectClass *soc = NULL;
1026
1027 if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
1028 Attribute *a;
1029 const char *text = NULL;
1030 char textbuf[ 1024 ];
1031 size_t textlen = sizeof( textbuf );
1032 struct berval bv[ 2 ],
1033 *nvals;
1034 int rc = LDAP_SUCCESS;
1035
1036 a = attr_find( bsi->bsi_e->e_attrs,
1037 slap_schema.si_ad_objectClass );
1038 if ( a != NULL ) {
1039 nvals = a->a_nvals;
1040
1041 } else {
1042 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
1043 BER_BVZERO( &bv[ 1 ] );
1044 nvals = bv;
1045 }
1046
1047 rc = structural_class( nvals, &soc, NULL,
1048 &text, textbuf, textlen, op->o_tmpmemctx );
1049 if ( rc != LDAP_SUCCESS ) {
1050 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1051 "structural_class() failed %d (%s)\n",
1052 bsi->bsi_e->e_name.bv_val,
1053 rc, text ? text : "" );
1054 backsql_entry_clean( op, bsi->bsi_e );
1055 return rc;
1056 }
1057
1058 if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
1059 if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
1060 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1061 "computed structuralObjectClass %s "
1062 "does not match objectClass %s associated "
1063 "to entry\n",
1064 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
1065 bsi->bsi_oc->bom_oc->soc_cname.bv_val );
1066 backsql_entry_clean( op, bsi->bsi_e );
1067 return rc;
1068 }
1069
1070 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1071 "computed structuralObjectClass %s "
1072 "is subclass of objectClass %s associated "
1073 "to entry\n",
1074 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
1075 bsi->bsi_oc->bom_oc->soc_cname.bv_val );
1076 }
1077
1078 } else {
1079 soc = bsi->bsi_oc->bom_oc;
1080 }
1081
1082 rc = attr_merge_normalize_one( bsi->bsi_e,
1083 slap_schema.si_ad_structuralObjectClass,
1084 &soc->soc_cname,
1085 bsi->bsi_op->o_tmpmemctx );
1086 if ( rc != LDAP_SUCCESS ) {
1087 backsql_entry_clean( op, bsi->bsi_e );
1088 return rc;
1089 }
1090 }
1091
1092 done:;
1093 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n" );
1094
1095 return LDAP_SUCCESS;
1096 }
1097
1098