1 /* $NetBSD: entry-id.c,v 1.1.1.6 2018/02/06 01:53:18 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2017 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.1.1.6 2018/02/06 01:53:18 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 * 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 * 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 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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 char buf[ SLAP_TEXT_BUFLEN ]; 273 274 #ifdef LDAP_DEBUG 275 snprintf( buf, sizeof(buf), 276 "id=%s keyval=%s oc_id=%s dn=%s", 277 row.cols[ 0 ], row.cols[ 1 ], 278 row.cols[ 2 ], row.cols[ 3 ] ); 279 Debug( LDAP_DEBUG_TRACE, 280 " backsql_dn2id(\"%s\"): %s\n", 281 ndn->bv_val, buf, 0 ); 282 #endif /* LDAP_DEBUG */ 283 284 res = LDAP_SUCCESS; 285 if ( id != NULL ) { 286 struct berval dn; 287 288 id->eid_next = NULL; 289 290 #ifdef BACKSQL_ARBITRARY_KEY 291 ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id, 292 op->o_tmpmemctx ); 293 ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval, 294 op->o_tmpmemctx ); 295 #else /* ! BACKSQL_ARBITRARY_KEY */ 296 if ( BACKSQL_STR2ID( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) { 297 res = LDAP_OTHER; 298 goto done; 299 } 300 if ( BACKSQL_STR2ID( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) { 301 res = LDAP_OTHER; 302 goto done; 303 } 304 #endif /* ! BACKSQL_ARBITRARY_KEY */ 305 if ( BACKSQL_STR2ID( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) { 306 res = LDAP_OTHER; 307 goto done; 308 } 309 310 ber_str2bv( row.cols[ 3 ], 0, 0, &dn ); 311 312 if ( backsql_api_odbc2dn( op, rs, &dn ) ) { 313 res = LDAP_OTHER; 314 goto done; 315 } 316 317 res = dnPrettyNormal( NULL, &dn, 318 &id->eid_dn, &id->eid_ndn, 319 op->o_tmpmemctx ); 320 if ( res != LDAP_SUCCESS ) { 321 Debug( LDAP_DEBUG_TRACE, 322 " backsql_dn2id(\"%s\"): " 323 "dnPrettyNormal failed (%d: %s)\n", 324 realndn.bv_val, res, 325 ldap_err2string( res ) ); 326 327 /* cleanup... */ 328 (void)backsql_free_entryID( id, 0, op->o_tmpmemctx ); 329 } 330 331 if ( dn.bv_val != row.cols[ 3 ] ) { 332 free( dn.bv_val ); 333 } 334 } 335 336 } else { 337 res = LDAP_NO_SUCH_OBJECT; 338 if ( matched ) { 339 struct berval pdn = *ndn; 340 341 /* 342 * Look for matched 343 */ 344 rs->sr_matched = NULL; 345 while ( !be_issuffix( op->o_bd, &pdn ) ) { 346 char *matchedDN = NULL; 347 348 dnParent( &pdn, &pdn ); 349 350 /* 351 * Empty DN ("") defaults to LDAP_SUCCESS 352 */ 353 rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 ); 354 switch ( rs->sr_err ) { 355 case LDAP_NO_SUCH_OBJECT: 356 /* try another one */ 357 break; 358 359 case LDAP_SUCCESS: 360 matchedDN = pdn.bv_val; 361 /* fail over to next case */ 362 363 default: 364 rs->sr_err = LDAP_NO_SUCH_OBJECT; 365 rs->sr_matched = matchedDN; 366 goto done; 367 } 368 } 369 } 370 } 371 372 done:; 373 backsql_FreeRow_x( &row, op->o_tmpmemctx ); 374 375 Debug( LDAP_DEBUG_TRACE, 376 "<==backsql_dn2id(\"%s\"): err=%d\n", 377 ndn->bv_val, res, 0 ); 378 if ( sth != SQL_NULL_HSTMT ) { 379 SQLFreeStmt( sth, SQL_DROP ); 380 } 381 382 if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) { 383 ch_free( realndn.bv_val ); 384 } 385 386 return res; 387 } 388 389 int 390 backsql_count_children( 391 Operation *op, 392 SQLHDBC dbh, 393 struct berval *dn, 394 unsigned long *nchildren ) 395 { 396 backsql_info *bi = (backsql_info *)op->o_bd->be_private; 397 SQLHSTMT sth = SQL_NULL_HSTMT; 398 BACKSQL_ROW_NTS row; 399 RETCODE rc; 400 int res = LDAP_SUCCESS; 401 402 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n", 403 dn->bv_val, 0, 0 ); 404 405 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) { 406 Debug( LDAP_DEBUG_TRACE, 407 "backsql_count_children(): DN \"%s\" (%ld bytes) " 408 "exceeds max DN length (%d):\n", 409 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN ); 410 return LDAP_OTHER; 411 } 412 413 /* begin TimesTen */ 414 assert( bi->sql_has_children_query != NULL ); 415 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n", 416 bi->sql_has_children_query, 0, 0); 417 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 ); 418 if ( rc != SQL_SUCCESS ) { 419 Debug( LDAP_DEBUG_TRACE, 420 "backsql_count_children(): error preparing SQL:\n%s", 421 bi->sql_has_children_query, 0, 0); 422 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); 423 SQLFreeStmt( sth, SQL_DROP ); 424 return LDAP_OTHER; 425 } 426 427 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn ); 428 if ( rc != SQL_SUCCESS) { 429 /* end TimesTen */ 430 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): " 431 "error binding dn=\"%s\" parameter:\n", 432 dn->bv_val, 0, 0 ); 433 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); 434 SQLFreeStmt( sth, SQL_DROP ); 435 return LDAP_OTHER; 436 } 437 438 rc = SQLExecute( sth ); 439 if ( rc != SQL_SUCCESS ) { 440 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): " 441 "error executing query (\"%s\", \"%s\"):\n", 442 bi->sql_has_children_query, dn->bv_val, 0 ); 443 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); 444 SQLFreeStmt( sth, SQL_DROP ); 445 return LDAP_OTHER; 446 } 447 448 backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx ); 449 450 rc = SQLFetch( sth ); 451 if ( BACKSQL_SUCCESS( rc ) ) { 452 char *end; 453 454 *nchildren = strtol( row.cols[ 0 ], &end, 0 ); 455 if ( end == row.cols[ 0 ] ) { 456 res = LDAP_OTHER; 457 458 } else { 459 switch ( end[ 0 ] ) { 460 case '\0': 461 break; 462 463 case '.': { 464 unsigned long ul; 465 466 /* FIXME: braindead RDBMSes return 467 * a fractional number from COUNT! 468 */ 469 if ( lutil_atoul( &ul, end + 1 ) != 0 || ul != 0 ) { 470 res = LDAP_OTHER; 471 } 472 } break; 473 474 default: 475 res = LDAP_OTHER; 476 } 477 } 478 479 } else { 480 res = LDAP_OTHER; 481 } 482 backsql_FreeRow_x( &row, op->o_tmpmemctx ); 483 484 SQLFreeStmt( sth, SQL_DROP ); 485 486 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n", 487 *nchildren, 0, 0 ); 488 489 return res; 490 } 491 492 int 493 backsql_has_children( 494 Operation *op, 495 SQLHDBC dbh, 496 struct berval *dn ) 497 { 498 unsigned long nchildren; 499 int rc; 500 501 rc = backsql_count_children( op, dbh, dn, &nchildren ); 502 503 if ( rc == LDAP_SUCCESS ) { 504 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; 505 } 506 507 return rc; 508 } 509 510 static int 511 backsql_get_attr_vals( void *v_at, void *v_bsi ) 512 { 513 backsql_at_map_rec *at = v_at; 514 backsql_srch_info *bsi = v_bsi; 515 backsql_info *bi; 516 RETCODE rc; 517 SQLHSTMT sth = SQL_NULL_HSTMT; 518 BACKSQL_ROW_NTS row; 519 unsigned long i, 520 k = 0, 521 oldcount = 0, 522 res = 0; 523 #ifdef BACKSQL_COUNTQUERY 524 unsigned count, 525 j, 526 append = 0; 527 SQLLEN countsize = sizeof( count ); 528 Attribute *attr = NULL; 529 530 slap_mr_normalize_func *normfunc = NULL; 531 #endif /* BACKSQL_COUNTQUERY */ 532 #ifdef BACKSQL_PRETTY_VALIDATE 533 slap_syntax_validate_func *validate = NULL; 534 slap_syntax_transform_func *pretty = NULL; 535 #endif /* BACKSQL_PRETTY_VALIDATE */ 536 537 assert( at != NULL ); 538 assert( bsi != NULL ); 539 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): " 540 "oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n", 541 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 542 BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) ); 543 544 bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; 545 546 #ifdef BACKSQL_PRETTY_VALIDATE 547 validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate; 548 pretty = at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty; 549 550 if ( validate == NULL && pretty == NULL ) { 551 return 1; 552 } 553 #endif /* BACKSQL_PRETTY_VALIDATE */ 554 555 #ifdef BACKSQL_COUNTQUERY 556 if ( at->bam_true_ad->ad_type->sat_equality ) { 557 normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize; 558 } 559 560 /* Count how many rows will be returned. This avoids memory 561 * fragmentation that can result from loading the values in 562 * one by one and using realloc() 563 */ 564 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 ); 565 if ( rc != SQL_SUCCESS ) { 566 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 567 "error preparing count query: %s\n", 568 at->bam_countquery, 0, 0 ); 569 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); 570 return 1; 571 } 572 573 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, 574 &bsi->bsi_c_eid->eid_keyval ); 575 if ( rc != SQL_SUCCESS ) { 576 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 577 "error binding key value parameter\n", 0, 0, 0 ); 578 SQLFreeStmt( sth, SQL_DROP ); 579 return 1; 580 } 581 582 rc = SQLExecute( sth ); 583 if ( ! BACKSQL_SUCCESS( rc ) ) { 584 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 585 "error executing attribute count query '%s'\n", 586 at->bam_countquery, 0, 0 ); 587 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); 588 SQLFreeStmt( sth, SQL_DROP ); 589 return 1; 590 } 591 592 SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG, 593 (SQLPOINTER)&count, 594 (SQLINTEGER)sizeof( count ), 595 &countsize ); 596 597 rc = SQLFetch( sth ); 598 if ( rc != SQL_SUCCESS ) { 599 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 600 "error fetch results of count query: %s\n", 601 at->bam_countquery, 0, 0 ); 602 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); 603 SQLFreeStmt( sth, SQL_DROP ); 604 return 1; 605 } 606 607 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 608 "number of values in query: %u\n", count, 0, 0 ); 609 SQLFreeStmt( sth, SQL_DROP ); 610 if ( count == 0 ) { 611 return 1; 612 } 613 614 attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad ); 615 if ( attr != NULL ) { 616 BerVarray tmp; 617 618 if ( attr->a_vals != NULL ) { 619 oldcount = attr->a_numvals; 620 } 621 622 tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) ); 623 if ( tmp == NULL ) { 624 return 1; 625 } 626 attr->a_vals = tmp; 627 memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) ); 628 629 if ( normfunc ) { 630 tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) ); 631 if ( tmp == NULL ) { 632 return 1; 633 } 634 attr->a_nvals = tmp; 635 memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) ); 636 637 } else { 638 attr->a_nvals = attr->a_vals; 639 } 640 attr->a_numvals += count; 641 642 } else { 643 append = 1; 644 645 /* Make space for the array of values */ 646 attr = attr_alloc( at->bam_true_ad ); 647 attr->a_numvals = count; 648 attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) ); 649 if ( attr->a_vals == NULL ) { 650 Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 ); 651 ch_free( attr ); 652 return 1; 653 } 654 if ( normfunc ) { 655 attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) ); 656 if ( attr->a_nvals == NULL ) { 657 ch_free( attr->a_vals ); 658 ch_free( attr ); 659 return 1; 660 661 } 662 663 } else { 664 attr->a_nvals = attr->a_vals; 665 } 666 } 667 #endif /* BACKSQL_COUNTQUERY */ 668 669 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 ); 670 if ( rc != SQL_SUCCESS ) { 671 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 672 "error preparing query: %s\n", at->bam_query, 0, 0 ); 673 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); 674 #ifdef BACKSQL_COUNTQUERY 675 if ( append ) { 676 attr_free( attr ); 677 } 678 #endif /* BACKSQL_COUNTQUERY */ 679 return 1; 680 } 681 682 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, 683 &bsi->bsi_c_eid->eid_keyval ); 684 if ( rc != SQL_SUCCESS ) { 685 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 686 "error binding key value parameter\n", 0, 0, 0 ); 687 #ifdef BACKSQL_COUNTQUERY 688 if ( append ) { 689 attr_free( attr ); 690 } 691 #endif /* BACKSQL_COUNTQUERY */ 692 return 1; 693 } 694 695 #ifdef BACKSQL_TRACE 696 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 697 "query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query, 698 BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval), 0 ); 699 #endif /* BACKSQL_TRACE */ 700 701 rc = SQLExecute( sth ); 702 if ( ! BACKSQL_SUCCESS( rc ) ) { 703 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " 704 "error executing attribute query \"%s\"\n", 705 at->bam_query, 0, 0 ); 706 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); 707 SQLFreeStmt( sth, SQL_DROP ); 708 #ifdef BACKSQL_COUNTQUERY 709 if ( append ) { 710 attr_free( attr ); 711 } 712 #endif /* BACKSQL_COUNTQUERY */ 713 return 1; 714 } 715 716 backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx ); 717 #ifdef BACKSQL_COUNTQUERY 718 j = oldcount; 719 #endif /* BACKSQL_COUNTQUERY */ 720 for ( rc = SQLFetch( sth ), k = 0; 721 BACKSQL_SUCCESS( rc ); 722 rc = SQLFetch( sth ), k++ ) 723 { 724 for ( i = 0; i < (unsigned long)row.ncols; i++ ) { 725 726 if ( row.value_len[ i ] > 0 ) { 727 struct berval bv; 728 int retval; 729 #ifdef BACKSQL_TRACE 730 AttributeDescription *ad = NULL; 731 const char *text; 732 733 retval = slap_bv2ad( &row.col_names[ i ], &ad, &text ); 734 if ( retval != LDAP_SUCCESS ) { 735 Debug( LDAP_DEBUG_ANY, 736 "==>backsql_get_attr_vals(\"%s\"): " 737 "unable to find AttributeDescription %s " 738 "in schema (%d)\n", 739 bsi->bsi_e->e_name.bv_val, 740 row.col_names[ i ].bv_val, retval ); 741 res = 1; 742 goto done; 743 } 744 745 if ( ad != at->bam_ad ) { 746 Debug( LDAP_DEBUG_ANY, 747 "==>backsql_get_attr_vals(\"%s\"): " 748 "column name %s differs from " 749 "AttributeDescription %s\n", 750 bsi->bsi_e->e_name.bv_val, 751 ad->ad_cname.bv_val, 752 at->bam_ad->ad_cname.bv_val ); 753 res = 1; 754 goto done; 755 } 756 #endif /* BACKSQL_TRACE */ 757 758 /* ITS#3386, ITS#3113 - 20070308 759 * If a binary is fetched? 760 * must use the actual size read 761 * from the database. 762 */ 763 if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) { 764 #ifdef BACKSQL_TRACE 765 Debug( LDAP_DEBUG_ANY, 766 "==>backsql_get_attr_vals(\"%s\"): " 767 "column name %s: data is binary; " 768 "using database size %ld\n", 769 bsi->bsi_e->e_name.bv_val, 770 ad->ad_cname.bv_val, 771 row.value_len[ i ] ); 772 #endif /* BACKSQL_TRACE */ 773 bv.bv_val = row.cols[ i ]; 774 bv.bv_len = row.value_len[ i ]; 775 776 } else { 777 ber_str2bv( row.cols[ i ], 0, 0, &bv ); 778 } 779 780 #ifdef BACKSQL_PRETTY_VALIDATE 781 if ( pretty ) { 782 struct berval pbv; 783 784 retval = pretty( at->bam_true_ad->ad_type->sat_syntax, 785 &bv, &pbv, bsi->bsi_op->o_tmpmemctx ); 786 bv = pbv; 787 788 } else { 789 retval = validate( at->bam_true_ad->ad_type->sat_syntax, 790 &bv ); 791 } 792 793 if ( retval != LDAP_SUCCESS ) { 794 char buf[ SLAP_TEXT_BUFLEN ]; 795 796 /* FIXME: we're ignoring invalid values, 797 * but we're accepting the attributes; 798 * should we fail at all? */ 799 snprintf( buf, sizeof( buf ), 800 "unable to %s value #%lu " 801 "of AttributeDescription %s", 802 pretty ? "prettify" : "validate", 803 k - oldcount, 804 at->bam_ad->ad_cname.bv_val ); 805 Debug( LDAP_DEBUG_TRACE, 806 "==>backsql_get_attr_vals(\"%s\"): " 807 "%s (%d)\n", 808 bsi->bsi_e->e_name.bv_val, buf, retval ); 809 continue; 810 } 811 #endif /* BACKSQL_PRETTY_VALIDATE */ 812 813 #ifndef BACKSQL_COUNTQUERY 814 (void)backsql_entry_addattr( bsi->bsi_e, 815 at->bam_true_ad, &bv, 816 bsi->bsi_op->o_tmpmemctx ); 817 818 #else /* BACKSQL_COUNTQUERY */ 819 if ( normfunc ) { 820 struct berval nbv; 821 822 retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 823 at->bam_true_ad->ad_type->sat_syntax, 824 at->bam_true_ad->ad_type->sat_equality, 825 &bv, &nbv, 826 bsi->bsi_op->o_tmpmemctx ); 827 828 if ( retval != LDAP_SUCCESS ) { 829 char buf[ SLAP_TEXT_BUFLEN ]; 830 831 /* FIXME: we're ignoring invalid values, 832 * but we're accepting the attributes; 833 * should we fail at all? */ 834 snprintf( buf, sizeof( buf ), 835 "unable to normalize value #%lu " 836 "of AttributeDescription %s", 837 k - oldcount, 838 at->bam_ad->ad_cname.bv_val ); 839 Debug( LDAP_DEBUG_TRACE, 840 "==>backsql_get_attr_vals(\"%s\"): " 841 "%s (%d)\n", 842 bsi->bsi_e->e_name.bv_val, buf, retval ); 843 844 #ifdef BACKSQL_PRETTY_VALIDATE 845 if ( pretty ) { 846 bsi->bsi_op->o_tmpfree( bv.bv_val, 847 bsi->bsi_op->o_tmpmemctx ); 848 } 849 #endif /* BACKSQL_PRETTY_VALIDATE */ 850 851 continue; 852 } 853 ber_dupbv( &attr->a_nvals[ j ], &nbv ); 854 bsi->bsi_op->o_tmpfree( nbv.bv_val, 855 bsi->bsi_op->o_tmpmemctx ); 856 } 857 858 ber_dupbv( &attr->a_vals[ j ], &bv ); 859 860 assert( j < oldcount + count ); 861 j++; 862 #endif /* BACKSQL_COUNTQUERY */ 863 864 #ifdef BACKSQL_PRETTY_VALIDATE 865 if ( pretty ) { 866 bsi->bsi_op->o_tmpfree( bv.bv_val, 867 bsi->bsi_op->o_tmpmemctx ); 868 } 869 #endif /* BACKSQL_PRETTY_VALIDATE */ 870 871 #ifdef BACKSQL_TRACE 872 Debug( LDAP_DEBUG_TRACE, "prec=%d\n", 873 (int)row.col_prec[ i ], 0, 0 ); 874 875 } else { 876 Debug( LDAP_DEBUG_TRACE, "NULL value " 877 "in this row for attribute \"%s\"\n", 878 row.col_names[ i ].bv_val, 0, 0 ); 879 #endif /* BACKSQL_TRACE */ 880 } 881 } 882 } 883 884 #ifdef BACKSQL_COUNTQUERY 885 if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) { 886 /* don't leave around attributes with no values */ 887 attr_free( attr ); 888 889 } else if ( append ) { 890 Attribute **ap; 891 892 for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next ) 893 /* goto last */ ; 894 *ap = attr; 895 } 896 #endif /* BACKSQL_COUNTQUERY */ 897 898 SQLFreeStmt( sth, SQL_DROP ); 899 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 ); 900 901 if ( at->bam_next ) { 902 res = backsql_get_attr_vals( at->bam_next, v_bsi ); 903 } else { 904 res = 1; 905 } 906 907 #ifdef BACKSQL_TRACE 908 done:; 909 #endif /* BACKSQL_TRACE */ 910 backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx ); 911 912 return res; 913 } 914 915 int 916 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid ) 917 { 918 Operation *op = bsi->bsi_op; 919 backsql_info *bi = (backsql_info *)op->o_bd->be_private; 920 int i; 921 int rc; 922 923 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 ); 924 925 assert( bsi->bsi_e != NULL ); 926 927 memset( bsi->bsi_e, 0, sizeof( Entry ) ); 928 929 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) { 930 (void)entry_dup2( bsi->bsi_e, bi->sql_baseObject ); 931 goto done; 932 } 933 934 bsi->bsi_e->e_attrs = NULL; 935 bsi->bsi_e->e_private = NULL; 936 937 if ( eid->eid_oc == NULL ) { 938 eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private, 939 eid->eid_oc_id ); 940 if ( eid->eid_oc == NULL ) { 941 Debug( LDAP_DEBUG_TRACE, 942 "backsql_id2entry(): unable to fetch objectClass with id=" BACKSQL_IDNUMFMT " for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n", 943 eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id), 944 eid->eid_dn.bv_val ); 945 return LDAP_OTHER; 946 } 947 } 948 bsi->bsi_oc = eid->eid_oc; 949 bsi->bsi_c_eid = eid; 950 951 ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx ); 952 ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx ); 953 954 #ifndef BACKSQL_ARBITRARY_KEY 955 /* FIXME: unused */ 956 bsi->bsi_e->e_id = eid->eid_id; 957 #endif /* ! BACKSQL_ARBITRARY_KEY */ 958 959 rc = attr_merge_normalize_one( bsi->bsi_e, 960 slap_schema.si_ad_objectClass, 961 &bsi->bsi_oc->bom_oc->soc_cname, 962 bsi->bsi_op->o_tmpmemctx ); 963 if ( rc != LDAP_SUCCESS ) { 964 backsql_entry_clean( op, bsi->bsi_e ); 965 return rc; 966 } 967 968 if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) ) 969 { 970 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " 971 "retrieving all attributes\n", 0, 0, 0 ); 972 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals, 973 bsi, 0, AVL_INORDER ); 974 975 } else { 976 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " 977 "custom attribute list\n", 0, 0, 0 ); 978 for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) { 979 backsql_at_map_rec **vat; 980 AttributeName *an = &bsi->bsi_attrs[ i ]; 981 int j; 982 983 /* if one of the attributes listed here is 984 * a subtype of another, it must be ignored, 985 * because subtypes are already dealt with 986 * by backsql_supad2at() 987 */ 988 for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) { 989 /* skip self */ 990 if ( j == i ) { 991 continue; 992 } 993 994 /* skip subtypes */ 995 if ( is_at_subtype( an->an_desc->ad_type, 996 bsi->bsi_attrs[ j ].an_desc->ad_type ) ) 997 { 998 goto next; 999 } 1000 } 1001 1002 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat ); 1003 if ( rc != 0 || vat == NULL ) { 1004 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " 1005 "attribute \"%s\" is not defined " 1006 "for objectlass \"%s\"\n", 1007 an->an_name.bv_val, 1008 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 ); 1009 continue; 1010 } 1011 1012 for ( j = 0; vat[j]; j++ ) { 1013 backsql_get_attr_vals( vat[j], bsi ); 1014 } 1015 1016 ch_free( vat ); 1017 1018 next:; 1019 } 1020 } 1021 1022 if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) { 1023 Attribute *a_entryUUID, 1024 **ap; 1025 1026 a_entryUUID = backsql_operational_entryUUID( bi, eid ); 1027 if ( a_entryUUID != NULL ) { 1028 for ( ap = &bsi->bsi_e->e_attrs; 1029 *ap; 1030 ap = &(*ap)->a_next ); 1031 1032 *ap = a_entryUUID; 1033 } 1034 } 1035 1036 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER ) 1037 || an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs ) 1038 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) ) 1039 { 1040 ObjectClass *soc = NULL; 1041 1042 if ( BACKSQL_CHECK_SCHEMA( bi ) ) { 1043 Attribute *a; 1044 const char *text = NULL; 1045 char textbuf[ 1024 ]; 1046 size_t textlen = sizeof( textbuf ); 1047 struct berval bv[ 2 ], 1048 *nvals; 1049 int rc = LDAP_SUCCESS; 1050 1051 a = attr_find( bsi->bsi_e->e_attrs, 1052 slap_schema.si_ad_objectClass ); 1053 if ( a != NULL ) { 1054 nvals = a->a_nvals; 1055 1056 } else { 1057 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname; 1058 BER_BVZERO( &bv[ 1 ] ); 1059 nvals = bv; 1060 } 1061 1062 rc = structural_class( nvals, &soc, NULL, 1063 &text, textbuf, textlen, op->o_tmpmemctx ); 1064 if ( rc != LDAP_SUCCESS ) { 1065 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " 1066 "structural_class() failed %d (%s)\n", 1067 bsi->bsi_e->e_name.bv_val, 1068 rc, text ? text : "" ); 1069 backsql_entry_clean( op, bsi->bsi_e ); 1070 return rc; 1071 } 1072 1073 if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) { 1074 if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) { 1075 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " 1076 "computed structuralObjectClass %s " 1077 "does not match objectClass %s associated " 1078 "to entry\n", 1079 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val, 1080 bsi->bsi_oc->bom_oc->soc_cname.bv_val ); 1081 backsql_entry_clean( op, bsi->bsi_e ); 1082 return rc; 1083 } 1084 1085 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " 1086 "computed structuralObjectClass %s " 1087 "is subclass of objectClass %s associated " 1088 "to entry\n", 1089 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val, 1090 bsi->bsi_oc->bom_oc->soc_cname.bv_val ); 1091 } 1092 1093 } else { 1094 soc = bsi->bsi_oc->bom_oc; 1095 } 1096 1097 rc = attr_merge_normalize_one( bsi->bsi_e, 1098 slap_schema.si_ad_structuralObjectClass, 1099 &soc->soc_cname, 1100 bsi->bsi_op->o_tmpmemctx ); 1101 if ( rc != LDAP_SUCCESS ) { 1102 backsql_entry_clean( op, bsi->bsi_e ); 1103 return rc; 1104 } 1105 } 1106 1107 done:; 1108 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 ); 1109 1110 return LDAP_SUCCESS; 1111 } 1112 1113