1/* value.c - routines for dealing with values */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* 17 * Copyright (c) 1995 Regents of the University of Michigan. 18 * All rights reserved. 19 * 20 * Redistribution and use in source and binary forms are permitted 21 * provided that this notice is preserved and that due credit is given 22 * to the University of Michigan at Ann Arbor. The name of the University 23 * may not be used to endorse or promote products derived from this 24 * software without specific prior written permission. This software 25 * is provided ``as is'' without express or implied warranty. 26 */ 27 28#include "portable.h" 29 30#include <stdio.h> 31 32#include <ac/ctype.h> 33#include <ac/socket.h> 34#include <ac/string.h> 35#include <ac/time.h> 36 37#include <sys/stat.h> 38 39#include "slap.h" 40 41int 42value_add( 43 BerVarray *vals, 44 BerVarray addvals ) 45{ 46 int n, nn = 0; 47 BerVarray v2; 48 49 if ( addvals != NULL ) { 50 for ( ; !BER_BVISNULL( &addvals[nn] ); nn++ ) 51 ; /* NULL */ 52 } 53 54 if ( *vals == NULL ) { 55 *vals = (BerVarray) SLAP_MALLOC( (nn + 1) 56 * sizeof(struct berval) ); 57 if( *vals == NULL ) { 58 Debug(LDAP_DEBUG_TRACE, 59 "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 ); 60 return LBER_ERROR_MEMORY; 61 } 62 n = 0; 63 64 } else { 65 for ( n = 0; !BER_BVISNULL( &(*vals)[n] ); n++ ) { 66 ; /* Empty */ 67 } 68 *vals = (BerVarray) SLAP_REALLOC( (char *) *vals, 69 (n + nn + 1) * sizeof(struct berval) ); 70 if( *vals == NULL ) { 71 Debug(LDAP_DEBUG_TRACE, 72 "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 ); 73 return LBER_ERROR_MEMORY; 74 } 75 } 76 77 v2 = &(*vals)[n]; 78 for ( n = 0 ; n < nn; v2++, addvals++ ) { 79 ber_dupbv( v2, addvals ); 80 if ( BER_BVISNULL( v2 ) ) break; 81 } 82 BER_BVZERO( v2 ); 83 84 return LDAP_SUCCESS; 85} 86 87int 88value_add_one( 89 BerVarray *vals, 90 struct berval *addval ) 91{ 92 int n; 93 BerVarray v2; 94 95 if ( *vals == NULL ) { 96 *vals = (BerVarray) SLAP_MALLOC( 2 * sizeof(struct berval) ); 97 if( *vals == NULL ) { 98 Debug(LDAP_DEBUG_TRACE, 99 "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 ); 100 return LBER_ERROR_MEMORY; 101 } 102 n = 0; 103 104 } else { 105 for ( n = 0; !BER_BVISNULL( &(*vals)[n] ); n++ ) { 106 ; /* Empty */ 107 } 108 *vals = (BerVarray) SLAP_REALLOC( (char *) *vals, 109 (n + 2) * sizeof(struct berval) ); 110 if( *vals == NULL ) { 111 Debug(LDAP_DEBUG_TRACE, 112 "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 ); 113 return LBER_ERROR_MEMORY; 114 } 115 } 116 117 v2 = &(*vals)[n]; 118 ber_dupbv(v2, addval); 119 120 v2++; 121 BER_BVZERO( v2 ); 122 123 return LDAP_SUCCESS; 124} 125 126int asserted_value_validate_normalize( 127 AttributeDescription *ad, 128 MatchingRule *mr, 129 unsigned usage, 130 struct berval *in, 131 struct berval *out, 132 const char ** text, 133 void *ctx ) 134{ 135 int rc; 136 struct berval pval; 137 pval.bv_val = NULL; 138 139 /* we expect the value to be in the assertion syntax */ 140 assert( !SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) ); 141 142 if( mr == NULL ) { 143 *text = "inappropriate matching request"; 144 return LDAP_INAPPROPRIATE_MATCHING; 145 } 146 147 if( !mr->smr_match ) { 148 *text = "requested matching rule not supported"; 149 return LDAP_INAPPROPRIATE_MATCHING; 150 } 151 152 if( mr->smr_syntax->ssyn_pretty ) { 153 rc = (mr->smr_syntax->ssyn_pretty)( mr->smr_syntax, in, &pval, ctx ); 154 in = &pval; 155 156 } else if ( mr->smr_syntax->ssyn_validate ) { 157 rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in ); 158 159 } else { 160 *text = "inappropriate matching request"; 161 return LDAP_INAPPROPRIATE_MATCHING; 162 } 163 164 if( rc != LDAP_SUCCESS ) { 165 *text = "value does not conform to assertion syntax"; 166 return LDAP_INVALID_SYNTAX; 167 } 168 169 if( mr->smr_normalize ) { 170 rc = (mr->smr_normalize)( 171 usage|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 172 ad ? ad->ad_type->sat_syntax : NULL, 173 mr, in, out, ctx ); 174 175 if( pval.bv_val ) ber_memfree_x( pval.bv_val, ctx ); 176 177 if( rc != LDAP_SUCCESS ) { 178 *text = "unable to normalize value for matching"; 179 return LDAP_INVALID_SYNTAX; 180 } 181 182 } else if ( pval.bv_val != NULL ) { 183 *out = pval; 184 185 } else { 186 ber_dupbv_x( out, in, ctx ); 187 } 188 189 return LDAP_SUCCESS; 190} 191 192int 193value_match( 194 int *match, 195 AttributeDescription *ad, 196 MatchingRule *mr, 197 unsigned flags, 198 struct berval *v1, /* stored value */ 199 void *v2, /* assertion */ 200 const char ** text ) 201{ 202 int rc; 203 204 assert( mr != NULL ); 205 206 if( !mr->smr_match ) { 207 return LDAP_INAPPROPRIATE_MATCHING; 208 } 209 210 rc = (mr->smr_match)( match, flags, 211 ad->ad_type->sat_syntax, mr, v1, v2 ); 212 213 return rc; 214} 215 216int value_find_ex( 217 AttributeDescription *ad, 218 unsigned flags, 219 BerVarray vals, 220 struct berval *val, 221 void *ctx ) 222{ 223 int i; 224 int rc; 225 struct berval nval = BER_BVNULL; 226 MatchingRule *mr = ad->ad_type->sat_equality; 227 228 if( mr == NULL || !mr->smr_match ) { 229 return LDAP_INAPPROPRIATE_MATCHING; 230 } 231 232 assert( SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( flags ) != 0 ); 233 234 if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) && 235 mr->smr_normalize ) 236 { 237 rc = (mr->smr_normalize)( 238 flags & (SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK|SLAP_MR_VALUE_OF_SYNTAX), 239 ad->ad_type->sat_syntax, 240 mr, val, &nval, ctx ); 241 242 if( rc != LDAP_SUCCESS ) { 243 return LDAP_INVALID_SYNTAX; 244 } 245 } 246 247 for ( i = 0; vals[i].bv_val != NULL; i++ ) { 248 int match; 249 const char *text; 250 251 rc = value_match( &match, ad, mr, flags, 252 &vals[i], nval.bv_val == NULL ? val : &nval, &text ); 253 254 if( rc == LDAP_SUCCESS && match == 0 ) { 255 slap_sl_free( nval.bv_val, ctx ); 256 return rc; 257 } 258 } 259 260 slap_sl_free( nval.bv_val, ctx ); 261 return LDAP_NO_SUCH_ATTRIBUTE; 262} 263 264/* assign new indexes to an attribute's ordered values */ 265void 266ordered_value_renumber( Attribute *a ) 267{ 268 char *ptr, ibuf[64]; /* many digits */ 269 struct berval ibv, tmp, vtmp; 270 unsigned i; 271 272 ibv.bv_val = ibuf; 273 274 for (i=0; i<a->a_numvals; i++) { 275 ibv.bv_len = sprintf(ibv.bv_val, "{%u}", i); 276 vtmp = a->a_vals[i]; 277 if ( vtmp.bv_val[0] == '{' ) { 278 ptr = ber_bvchr(&vtmp, '}'); 279 assert( ptr != NULL ); 280 ++ptr; 281 vtmp.bv_len -= ptr - vtmp.bv_val; 282 vtmp.bv_val = ptr; 283 } 284 tmp.bv_len = ibv.bv_len + vtmp.bv_len; 285 tmp.bv_val = ch_malloc( tmp.bv_len + 1 ); 286 strcpy( tmp.bv_val, ibv.bv_val ); 287 AC_MEMCPY( tmp.bv_val + ibv.bv_len, vtmp.bv_val, vtmp.bv_len ); 288 tmp.bv_val[tmp.bv_len] = '\0'; 289 ch_free( a->a_vals[i].bv_val ); 290 a->a_vals[i] = tmp; 291 292 if ( a->a_nvals && a->a_nvals != a->a_vals ) { 293 vtmp = a->a_nvals[i]; 294 if ( vtmp.bv_val[0] == '{' ) { 295 ptr = ber_bvchr(&vtmp, '}'); 296 assert( ptr != NULL ); 297 ++ptr; 298 vtmp.bv_len -= ptr - vtmp.bv_val; 299 vtmp.bv_val = ptr; 300 } 301 tmp.bv_len = ibv.bv_len + vtmp.bv_len; 302 tmp.bv_val = ch_malloc( tmp.bv_len + 1 ); 303 strcpy( tmp.bv_val, ibv.bv_val ); 304 AC_MEMCPY( tmp.bv_val + ibv.bv_len, vtmp.bv_val, vtmp.bv_len ); 305 tmp.bv_val[tmp.bv_len] = '\0'; 306 ch_free( a->a_nvals[i].bv_val ); 307 a->a_nvals[i] = tmp; 308 } 309 } 310} 311 312/* Sort the values in an X-ORDERED VALUES attribute. 313 * If the values have no index, index them in their given order. 314 * If the values have indexes, sort them. 315 * If some are indexed and some are not, return Error. 316 */ 317int 318ordered_value_sort( Attribute *a, int do_renumber ) 319{ 320 int i, vals; 321 int index = 0, noindex = 0, renumber = 0, gotnvals = 0; 322 struct berval tmp; 323 324 if ( a->a_nvals && a->a_nvals != a->a_vals ) 325 gotnvals = 1; 326 327 /* count attrs, look for index */ 328 for (i=0; a->a_vals[i].bv_val; i++) { 329 if ( a->a_vals[i].bv_val[0] == '{' ) { 330 char *ptr; 331 index = 1; 332 ptr = ber_bvchr( &a->a_vals[i], '}' ); 333 if ( !ptr ) 334 return LDAP_INVALID_SYNTAX; 335 if ( noindex ) 336 return LDAP_INVALID_SYNTAX; 337 } else { 338 noindex = 1; 339 if ( index ) 340 return LDAP_INVALID_SYNTAX; 341 } 342 } 343 vals = i; 344 345 /* If values have indexes, sort the values */ 346 if ( index ) { 347 int *indexes, j, idx; 348 struct berval ntmp; 349 350#if 0 351 /* Strip index from normalized values */ 352 if ( !a->a_nvals || a->a_vals == a->a_nvals ) { 353 a->a_nvals = ch_malloc( (vals+1)*sizeof(struct berval)); 354 BER_BVZERO(a->a_nvals+vals); 355 for ( i=0; i<vals; i++ ) { 356 char *ptr = ber_bvchr(&a->a_vals[i], '}') + 1; 357 a->a_nvals[i].bv_len = a->a_vals[i].bv_len - 358 (ptr - a->a_vals[i].bv_val); 359 a->a_nvals[i].bv_val = ch_malloc( a->a_nvals[i].bv_len + 1); 360 strcpy(a->a_nvals[i].bv_val, ptr ); 361 } 362 } else { 363 for ( i=0; i<vals; i++ ) { 364 char *ptr = ber_bvchr(&a->a_nvals[i], '}') + 1; 365 a->a_nvals[i].bv_len -= ptr - a->a_nvals[i].bv_val; 366 strcpy(a->a_nvals[i].bv_val, ptr); 367 } 368 } 369#endif 370 371 indexes = ch_malloc( vals * sizeof(int) ); 372 for ( i=0; i<vals; i++) { 373 char *ptr; 374 indexes[i] = strtol(a->a_vals[i].bv_val+1, &ptr, 0); 375 if ( *ptr != '}' ) { 376 ch_free( indexes ); 377 return LDAP_INVALID_SYNTAX; 378 } 379 } 380 381 /* Insertion sort */ 382 for ( i=1; i<vals; i++ ) { 383 idx = indexes[i]; 384 tmp = a->a_vals[i]; 385 if ( gotnvals ) ntmp = a->a_nvals[i]; 386 j = i; 387 while ((j > 0) && (indexes[j-1] > idx)) { 388 indexes[j] = indexes[j-1]; 389 a->a_vals[j] = a->a_vals[j-1]; 390 if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1]; 391 j--; 392 } 393 indexes[j] = idx; 394 a->a_vals[j] = tmp; 395 if ( gotnvals ) a->a_nvals[j] = ntmp; 396 } 397 398 /* If range is not contiguous, must renumber */ 399 if ( indexes[0] != 0 || indexes[vals-1] != vals-1 ) { 400 renumber = 1; 401 } 402 ch_free( indexes ); 403 } else { 404 renumber = 1; 405 } 406 407 if ( do_renumber && renumber ) 408 ordered_value_renumber( a ); 409 410 return 0; 411} 412 413/* 414 * wrapper for validate function 415 * uses the validate function of the syntax after removing 416 * the index, if allowed and present 417 */ 418int 419ordered_value_validate( 420 AttributeDescription *ad, 421 struct berval *in, 422 int mop ) 423{ 424 struct berval bv = *in; 425 426 assert( ad->ad_type->sat_syntax != NULL ); 427 assert( ad->ad_type->sat_syntax->ssyn_validate != NULL ); 428 429 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) { 430 431 /* Skip past the assertion index */ 432 if ( bv.bv_val[0] == '{' ) { 433 char *ptr; 434 435 ptr = ber_bvchr( &bv, '}' ); 436 if ( ptr != NULL ) { 437 struct berval ns; 438 439 ns.bv_val = bv.bv_val + 1; 440 ns.bv_len = ptr - ns.bv_val; 441 442 if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) { 443 ptr++; 444 bv.bv_len -= ptr - bv.bv_val; 445 bv.bv_val = ptr; 446 in = &bv; 447 /* If deleting by index, just succeed */ 448 if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ) ) { 449 return LDAP_SUCCESS; 450 } 451 } 452 } 453 } 454 } 455 456 return ad->ad_type->sat_syntax->ssyn_validate( ad->ad_type->sat_syntax, in ); 457} 458 459/* 460 * wrapper for pretty function 461 * uses the pretty function of the syntax after removing 462 * the index, if allowed and present; in case, it's prepended 463 * to the pretty value 464 */ 465int 466ordered_value_pretty( 467 AttributeDescription *ad, 468 struct berval *val, 469 struct berval *out, 470 void *ctx ) 471{ 472 struct berval bv, 473 idx = BER_BVNULL; 474 int rc; 475 476 assert( ad->ad_type->sat_syntax != NULL ); 477 assert( ad->ad_type->sat_syntax->ssyn_pretty != NULL ); 478 assert( val != NULL ); 479 assert( out != NULL ); 480 481 bv = *val; 482 483 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) { 484 485 /* Skip past the assertion index */ 486 if ( bv.bv_val[0] == '{' ) { 487 char *ptr; 488 489 ptr = ber_bvchr( &bv, '}' ); 490 if ( ptr != NULL ) { 491 struct berval ns; 492 493 ns.bv_val = bv.bv_val + 1; 494 ns.bv_len = ptr - ns.bv_val; 495 496 if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) { 497 ptr++; 498 499 idx = bv; 500 idx.bv_len = ptr - bv.bv_val; 501 502 bv.bv_len -= idx.bv_len; 503 bv.bv_val = ptr; 504 505 val = &bv; 506 } 507 } 508 } 509 } 510 511 rc = ad->ad_type->sat_syntax->ssyn_pretty( ad->ad_type->sat_syntax, val, out, ctx ); 512 513 if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &idx ) ) { 514 bv = *out; 515 516 out->bv_len = idx.bv_len + bv.bv_len; 517 out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx ); 518 519 AC_MEMCPY( out->bv_val, idx.bv_val, idx.bv_len ); 520 AC_MEMCPY( &out->bv_val[ idx.bv_len ], bv.bv_val, bv.bv_len + 1 ); 521 522 ber_memfree_x( bv.bv_val, ctx ); 523 } 524 525 return rc; 526} 527 528/* 529 * wrapper for normalize function 530 * uses the normalize function of the attribute description equality rule 531 * after removing the index, if allowed and present; in case, it's 532 * prepended to the value 533 */ 534int 535ordered_value_normalize( 536 slap_mask_t usage, 537 AttributeDescription *ad, 538 MatchingRule *mr, 539 struct berval *val, 540 struct berval *normalized, 541 void *ctx ) 542{ 543 struct berval bv, 544 idx = BER_BVNULL; 545 int rc; 546 547 assert( ad->ad_type->sat_equality != NULL ); 548 assert( ad->ad_type->sat_equality->smr_normalize != NULL ); 549 assert( val != NULL ); 550 assert( normalized != NULL ); 551 552 bv = *val; 553 554 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) { 555 556 /* Skip past the assertion index */ 557 if ( bv.bv_val[ 0 ] == '{' ) { 558 char *ptr; 559 560 ptr = ber_bvchr( &bv, '}' ); 561 if ( ptr != NULL ) { 562 struct berval ns; 563 564 ns.bv_val = bv.bv_val + 1; 565 ns.bv_len = ptr - ns.bv_val; 566 567 if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) { 568 ptr++; 569 570 idx = bv; 571 idx.bv_len = ptr - bv.bv_val; 572 573 bv.bv_len -= idx.bv_len; 574 bv.bv_val = ptr; 575 576 /* validator will already prevent this for Adds */ 577 if ( BER_BVISEMPTY( &bv )) { 578 ber_dupbv_x( normalized, &idx, ctx ); 579 return LDAP_SUCCESS; 580 } 581 val = &bv; 582 } 583 } 584 } 585 } 586 587 rc = ad->ad_type->sat_equality->smr_normalize( usage, 588 ad->ad_type->sat_syntax, mr, val, normalized, ctx ); 589 590 if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &idx ) ) { 591 bv = *normalized; 592 593 normalized->bv_len = idx.bv_len + bv.bv_len; 594 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx ); 595 596 AC_MEMCPY( normalized->bv_val, idx.bv_val, idx.bv_len ); 597 AC_MEMCPY( &normalized->bv_val[ idx.bv_len ], bv.bv_val, bv.bv_len + 1 ); 598 599 ber_memfree_x( bv.bv_val, ctx ); 600 } 601 602 return rc; 603} 604 605/* A wrapper for value match, handles Equality matches for attributes 606 * with ordered values. 607 */ 608int 609ordered_value_match( 610 int *match, 611 AttributeDescription *ad, 612 MatchingRule *mr, 613 unsigned flags, 614 struct berval *v1, /* stored value */ 615 struct berval *v2, /* assertion */ 616 const char ** text ) 617{ 618 struct berval bv1, bv2; 619 620 /* X-ORDERED VALUES equality matching: 621 * If (SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX) that means we are 622 * comparing two attribute values. In this case, we want to ignore 623 * the ordering index of both values, we just want to know if their 624 * main values are equal. 625 * 626 * If (SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX) then we are comparing 627 * an assertion against an attribute value. 628 * If the assertion has no index, the index of the value is ignored. 629 * If the assertion has only an index, the remainder of the value is 630 * ignored. 631 * If the assertion has index and value, both are compared. 632 */ 633 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) { 634 char *ptr; 635 struct berval ns1 = BER_BVNULL, ns2 = BER_BVNULL; 636 637 bv1 = *v1; 638 bv2 = *v2; 639 640 /* Skip past the assertion index */ 641 if ( bv2.bv_val[0] == '{' ) { 642 ptr = ber_bvchr( &bv2, '}' ); 643 if ( ptr != NULL ) { 644 ns2.bv_val = bv2.bv_val + 1; 645 ns2.bv_len = ptr - ns2.bv_val; 646 647 if ( numericStringValidate( NULL, &ns2 ) == LDAP_SUCCESS ) { 648 ptr++; 649 bv2.bv_len -= ptr - bv2.bv_val; 650 bv2.bv_val = ptr; 651 v2 = &bv2; 652 } 653 } 654 } 655 656 /* Skip past the attribute index */ 657 if ( bv1.bv_val[0] == '{' ) { 658 ptr = ber_bvchr( &bv1, '}' ); 659 if ( ptr != NULL ) { 660 ns1.bv_val = bv1.bv_val + 1; 661 ns1.bv_len = ptr - ns1.bv_val; 662 663 if ( numericStringValidate( NULL, &ns1 ) == LDAP_SUCCESS ) { 664 ptr++; 665 bv1.bv_len -= ptr - bv1.bv_val; 666 bv1.bv_val = ptr; 667 v1 = &bv1; 668 } 669 } 670 } 671 672 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) { 673 if ( !BER_BVISNULL( &ns2 ) && !BER_BVISNULL( &ns1 ) ) { 674 /* compare index values first */ 675 (void)octetStringOrderingMatch( match, 0, NULL, NULL, &ns1, &ns2 ); 676 677 /* If not equal, or we're only comparing the index, 678 * return result now. 679 */ 680 if ( *match != 0 || BER_BVISEMPTY( &bv2 ) ) { 681 return LDAP_SUCCESS; 682 } 683 } 684 } 685 686 } 687 688 if ( !mr || !mr->smr_match ) { 689 *match = ber_bvcmp( v1, v2 ); 690 return LDAP_SUCCESS; 691 } 692 693 return value_match( match, ad, mr, flags, v1, v2, text ); 694} 695 696int 697ordered_value_add( 698 Entry *e, 699 AttributeDescription *ad, 700 Attribute *a, 701 BerVarray vals, 702 BerVarray nvals 703) 704{ 705 int i, j, k, anum, vnum; 706 BerVarray new, nnew = NULL; 707 708 /* count new vals */ 709 for (i=0; !BER_BVISNULL( vals+i ); i++) ; 710 vnum = i; 711 712 if ( a ) { 713 ordered_value_sort( a, 0 ); 714 } else { 715 Attribute **ap; 716 for ( ap=&e->e_attrs; *ap; ap = &(*ap)->a_next ) ; 717 a = attr_alloc( ad ); 718 *ap = a; 719 } 720 anum = a->a_numvals; 721 722 new = ch_malloc( (anum+vnum+1) * sizeof(struct berval)); 723 724 /* sanity check: if normalized modifications come in, either 725 * no values are present or normalized existing values differ 726 * from non-normalized; if no normalized modifications come in, 727 * either no values are present or normalized existing values 728 * don't differ from non-normalized */ 729 if ( nvals != NULL ) { 730 assert( nvals != vals ); 731 assert( a->a_nvals == NULL || a->a_nvals != a->a_vals ); 732 733 } else { 734 assert( a->a_nvals == NULL || a->a_nvals == a->a_vals ); 735 } 736 737 if ( ( a->a_nvals && a->a_nvals != a->a_vals ) || nvals != NULL ) { 738 nnew = ch_malloc( (anum+vnum+1) * sizeof(struct berval)); 739 /* Shouldn't happen... */ 740 if ( !nvals ) nvals = vals; 741 } 742 if ( anum ) { 743 AC_MEMCPY( new, a->a_vals, anum * sizeof(struct berval)); 744 if ( nnew && a->a_nvals ) 745 AC_MEMCPY( nnew, a->a_nvals, anum * sizeof(struct berval)); 746 } 747 748 for (i=0; i<vnum; i++) { 749 char *next; 750 751 k = -1; 752 if ( vals[i].bv_val[0] == '{' ) { 753 /* FIXME: strtol() could go past end... */ 754 k = strtol( vals[i].bv_val + 1, &next, 0 ); 755 if ( next == vals[i].bv_val + 1 || 756 next[ 0 ] != '}' || 757 (ber_len_t) (next - vals[i].bv_val) > vals[i].bv_len ) 758 { 759 ch_free( nnew ); 760 ch_free( new ); 761 return -1; 762 } 763 if ( k > anum ) k = -1; 764 } 765 /* No index, or index is greater than current number of 766 * values, just tack onto the end 767 */ 768 if ( k < 0 ) { 769 ber_dupbv( new+anum, vals+i ); 770 if ( nnew ) ber_dupbv( nnew+anum, nvals+i ); 771 772 /* Indexed, push everything else down one and insert */ 773 } else { 774 for (j=anum; j>k; j--) { 775 new[j] = new[j-1]; 776 if ( nnew ) nnew[j] = nnew[j-1]; 777 } 778 ber_dupbv( new+k, vals+i ); 779 if ( nnew ) ber_dupbv( nnew+k, nvals+i ); 780 } 781 anum++; 782 } 783 BER_BVZERO( new+anum ); 784 ch_free( a->a_vals ); 785 a->a_vals = new; 786 if ( nnew ) { 787 BER_BVZERO( nnew+anum ); 788 ch_free( a->a_nvals ); 789 a->a_nvals = nnew; 790 } else { 791 a->a_nvals = a->a_vals; 792 } 793 794 a->a_numvals = anum; 795 ordered_value_renumber( a ); 796 797 return 0; 798} 799