1 /* schema_init.c - init builtin schema */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/schema_init.c,v 1.386.2.20 2008/04/14 20:01:31 quanah Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 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 #include "portable.h" 18 19 #include <stdio.h> 20 #ifdef HAVE_LIMITS_H 21 #include <limits.h> 22 #endif 23 24 #include <ac/ctype.h> 25 #include <ac/errno.h> 26 #include <ac/string.h> 27 #include <ac/socket.h> 28 29 #include "slap.h" 30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */ 31 32 #include "ldap_utf8.h" 33 34 #include "lutil.h" 35 #include "lutil_hash.h" 36 #define HASH_BYTES LUTIL_HASH_BYTES 37 #define HASH_CONTEXT lutil_HASH_CTX 38 #define HASH_Init(c) lutil_HASHInit(c) 39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len) 40 #define HASH_Final(d,c) lutil_HASHFinal(d,c) 41 42 /* approx matching rules */ 43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4" 44 #define directoryStringApproxMatch approxMatch 45 #define directoryStringApproxIndexer approxIndexer 46 #define directoryStringApproxFilter approxFilter 47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5" 48 #define IA5StringApproxMatch approxMatch 49 #define IA5StringApproxIndexer approxIndexer 50 #define IA5StringApproxFilter approxFilter 51 52 /* Change Sequence Number (CSN) - much of this will change */ 53 #define csnMatch octetStringMatch 54 #define csnOrderingMatch octetStringOrderingMatch 55 #define csnIndexer generalizedTimeIndexer 56 #define csnFilter generalizedTimeFilter 57 58 #define authzMatch octetStringMatch 59 60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT; 61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT; 62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT; 63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT; 64 65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT; 66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( 67 SLAP_INDEX_INTLEN_DEFAULT ); 68 69 ldap_pvt_thread_mutex_t ad_undef_mutex; 70 ldap_pvt_thread_mutex_t oc_undef_mutex; 71 72 static int 73 generalizedTimeValidate( 74 Syntax *syntax, 75 struct berval *in ); 76 77 static int 78 inValidate( 79 Syntax *syntax, 80 struct berval *in ) 81 { 82 /* no value allowed */ 83 return LDAP_INVALID_SYNTAX; 84 } 85 86 static int 87 blobValidate( 88 Syntax *syntax, 89 struct berval *in ) 90 { 91 /* any value allowed */ 92 return LDAP_SUCCESS; 93 } 94 95 #define berValidate blobValidate 96 97 static int 98 sequenceValidate( 99 Syntax *syntax, 100 struct berval *in ) 101 { 102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX; 103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 104 105 return LDAP_SUCCESS; 106 } 107 108 /* X.509 related stuff */ 109 110 enum { 111 SLAP_X509_V1 = 0, 112 SLAP_X509_V2 = 1, 113 SLAP_X509_V3 = 2 114 }; 115 116 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) 117 118 enum { 119 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0, 120 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1, 121 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2, 122 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3 123 }; 124 125 enum { 126 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0 127 }; 128 129 /* X.509 certificate validation */ 130 static int certificateValidate( Syntax *syntax, struct berval *in ) 131 { 132 BerElementBuffer berbuf; 133 BerElement *ber = (BerElement *)&berbuf; 134 ber_tag_t tag; 135 ber_len_t len; 136 ber_int_t version = SLAP_X509_V1; 137 138 ber_init2( ber, in, LBER_USE_DER ); 139 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 141 tag = ber_skip_tag( ber, &len ); /* Sequence */ 142 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 143 tag = ber_peek_tag( ber, &len ); 144 /* Optional version */ 145 if ( tag == SLAP_X509_OPT_C_VERSION ) { 146 tag = ber_skip_tag( ber, &len ); 147 tag = ber_get_int( ber, &version ); 148 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 149 } 150 /* NOTE: don't try to parse Serial, because it might be longer 151 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */ 152 tag = ber_skip_tag( ber, &len ); /* Serial */ 153 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 154 ber_skip_data( ber, len ); 155 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 157 ber_skip_data( ber, len ); 158 tag = ber_skip_tag( ber, &len ); /* Issuer DN */ 159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 160 ber_skip_data( ber, len ); 161 tag = ber_skip_tag( ber, &len ); /* Validity */ 162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 163 ber_skip_data( ber, len ); 164 tag = ber_skip_tag( ber, &len ); /* Subject DN */ 165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 166 ber_skip_data( ber, len ); 167 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */ 168 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 169 ber_skip_data( ber, len ); 170 tag = ber_skip_tag( ber, &len ); 171 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */ 172 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 173 ber_skip_data( ber, len ); 174 tag = ber_skip_tag( ber, &len ); 175 } 176 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */ 177 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 178 ber_skip_data( ber, len ); 179 tag = ber_skip_tag( ber, &len ); 180 } 181 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */ 182 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX; 183 tag = ber_skip_tag( ber, &len ); 184 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 185 ber_skip_data( ber, len ); 186 tag = ber_skip_tag( ber, &len ); 187 } 188 /* signatureAlgorithm */ 189 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 190 ber_skip_data( ber, len ); 191 tag = ber_skip_tag( ber, &len ); 192 /* Signature */ 193 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 194 ber_skip_data( ber, len ); 195 tag = ber_skip_tag( ber, &len ); 196 /* Must be at end now */ 197 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX; 198 return LDAP_SUCCESS; 199 } 200 201 /* X.509 certificate list validation */ 202 static int certificateListValidate( Syntax *syntax, struct berval *in ) 203 { 204 BerElementBuffer berbuf; 205 BerElement *ber = (BerElement *)&berbuf; 206 ber_tag_t tag; 207 ber_len_t len; 208 ber_int_t version = SLAP_X509_V1; 209 210 ber_init2( ber, in, LBER_USE_DER ); 211 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 213 tag = ber_skip_tag( ber, &len ); /* Sequence */ 214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 215 tag = ber_peek_tag( ber, &len ); 216 /* Optional version */ 217 if ( tag == LBER_INTEGER ) { 218 tag = ber_get_int( ber, &version ); 219 assert( tag == LBER_INTEGER ); 220 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 221 } 222 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 223 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 224 ber_skip_data( ber, len ); 225 tag = ber_skip_tag( ber, &len ); /* Issuer DN */ 226 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 227 ber_skip_data( ber, len ); 228 tag = ber_skip_tag( ber, &len ); /* thisUpdate */ 229 /* Time is a CHOICE { UTCTime, GeneralizedTime } */ 230 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX; 231 ber_skip_data( ber, len ); 232 /* Optional nextUpdate */ 233 tag = ber_skip_tag( ber, &len ); 234 if ( tag == 0x17U || tag == 0x18U ) { 235 ber_skip_data( ber, len ); 236 tag = ber_skip_tag( ber, &len ); 237 } 238 /* revokedCertificates - Sequence of Sequence, Optional */ 239 if ( tag == LBER_SEQUENCE ) { 240 ber_len_t seqlen; 241 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) { 242 /* Should NOT be empty */ 243 ber_skip_data( ber, len ); 244 tag = ber_skip_tag( ber, &len ); 245 } 246 } 247 /* Optional Extensions */ 248 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */ 249 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 250 tag = ber_skip_tag( ber, &len ); 251 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 252 ber_skip_data( ber, len ); 253 tag = ber_skip_tag( ber, &len ); 254 } 255 /* signatureAlgorithm */ 256 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 257 ber_skip_data( ber, len ); 258 tag = ber_skip_tag( ber, &len ); 259 /* Signature */ 260 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 261 ber_skip_data( ber, len ); 262 tag = ber_skip_tag( ber, &len ); 263 /* Must be at end now */ 264 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX; 265 return LDAP_SUCCESS; 266 } 267 268 int 269 octetStringMatch( 270 int *matchp, 271 slap_mask_t flags, 272 Syntax *syntax, 273 MatchingRule *mr, 274 struct berval *value, 275 void *assertedValue ) 276 { 277 struct berval *asserted = (struct berval *) assertedValue; 278 int match = value->bv_len - asserted->bv_len; 279 280 if( match == 0 ) { 281 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len ); 282 } 283 284 *matchp = match; 285 return LDAP_SUCCESS; 286 } 287 288 int 289 octetStringOrderingMatch( 290 int *matchp, 291 slap_mask_t flags, 292 Syntax *syntax, 293 MatchingRule *mr, 294 struct berval *value, 295 void *assertedValue ) 296 { 297 struct berval *asserted = (struct berval *) assertedValue; 298 ber_len_t v_len = value->bv_len; 299 ber_len_t av_len = asserted->bv_len; 300 301 int match = memcmp( value->bv_val, asserted->bv_val, 302 (v_len < av_len ? v_len : av_len) ); 303 304 if( match == 0 ) match = v_len - av_len; 305 306 *matchp = match; 307 return LDAP_SUCCESS; 308 } 309 310 static void 311 hashPreset( 312 HASH_CONTEXT *HASHcontext, 313 struct berval *prefix, 314 char pre, 315 Syntax *syntax, 316 MatchingRule *mr) 317 { 318 HASH_Init(HASHcontext); 319 if(prefix && prefix->bv_len > 0) { 320 HASH_Update(HASHcontext, 321 (unsigned char *)prefix->bv_val, prefix->bv_len); 322 } 323 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre)); 324 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen); 325 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen); 326 return; 327 } 328 329 static void 330 hashIter( 331 HASH_CONTEXT *HASHcontext, 332 unsigned char *HASHdigest, 333 unsigned char *value, 334 int len) 335 { 336 HASH_CONTEXT ctx = *HASHcontext; 337 HASH_Update( &ctx, value, len ); 338 HASH_Final( HASHdigest, &ctx ); 339 } 340 341 /* Index generation function */ 342 int octetStringIndexer( 343 slap_mask_t use, 344 slap_mask_t flags, 345 Syntax *syntax, 346 MatchingRule *mr, 347 struct berval *prefix, 348 BerVarray values, 349 BerVarray *keysp, 350 void *ctx ) 351 { 352 int i; 353 size_t slen, mlen; 354 BerVarray keys; 355 HASH_CONTEXT HASHcontext; 356 unsigned char HASHdigest[HASH_BYTES]; 357 struct berval digest; 358 digest.bv_val = (char *)HASHdigest; 359 digest.bv_len = sizeof(HASHdigest); 360 361 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 362 /* just count them */ 363 } 364 365 /* we should have at least one value at this point */ 366 assert( i > 0 ); 367 368 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 369 370 slen = syntax->ssyn_oidlen; 371 mlen = mr->smr_oidlen; 372 373 hashPreset( &HASHcontext, prefix, 0, syntax, mr); 374 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 375 hashIter( &HASHcontext, HASHdigest, 376 (unsigned char *)values[i].bv_val, values[i].bv_len ); 377 ber_dupbv_x( &keys[i], &digest, ctx ); 378 } 379 380 BER_BVZERO( &keys[i] ); 381 382 *keysp = keys; 383 384 return LDAP_SUCCESS; 385 } 386 387 /* Index generation function */ 388 int octetStringFilter( 389 slap_mask_t use, 390 slap_mask_t flags, 391 Syntax *syntax, 392 MatchingRule *mr, 393 struct berval *prefix, 394 void * assertedValue, 395 BerVarray *keysp, 396 void *ctx ) 397 { 398 size_t slen, mlen; 399 BerVarray keys; 400 HASH_CONTEXT HASHcontext; 401 unsigned char HASHdigest[HASH_BYTES]; 402 struct berval *value = (struct berval *) assertedValue; 403 struct berval digest; 404 digest.bv_val = (char *)HASHdigest; 405 digest.bv_len = sizeof(HASHdigest); 406 407 slen = syntax->ssyn_oidlen; 408 mlen = mr->smr_oidlen; 409 410 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 411 412 hashPreset( &HASHcontext, prefix, 0, syntax, mr ); 413 hashIter( &HASHcontext, HASHdigest, 414 (unsigned char *)value->bv_val, value->bv_len ); 415 416 ber_dupbv_x( keys, &digest, ctx ); 417 BER_BVZERO( &keys[1] ); 418 419 *keysp = keys; 420 421 return LDAP_SUCCESS; 422 } 423 424 static int 425 octetStringSubstringsMatch( 426 int *matchp, 427 slap_mask_t flags, 428 Syntax *syntax, 429 MatchingRule *mr, 430 struct berval *value, 431 void *assertedValue ) 432 { 433 int match = 0; 434 SubstringsAssertion *sub = assertedValue; 435 struct berval left = *value; 436 int i; 437 ber_len_t inlen = 0; 438 439 /* Add up asserted input length */ 440 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 441 inlen += sub->sa_initial.bv_len; 442 } 443 if ( sub->sa_any ) { 444 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 445 inlen += sub->sa_any[i].bv_len; 446 } 447 } 448 if ( !BER_BVISNULL( &sub->sa_final ) ) { 449 inlen += sub->sa_final.bv_len; 450 } 451 452 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 453 if ( inlen > left.bv_len ) { 454 match = 1; 455 goto done; 456 } 457 458 match = memcmp( sub->sa_initial.bv_val, left.bv_val, 459 sub->sa_initial.bv_len ); 460 461 if ( match != 0 ) { 462 goto done; 463 } 464 465 left.bv_val += sub->sa_initial.bv_len; 466 left.bv_len -= sub->sa_initial.bv_len; 467 inlen -= sub->sa_initial.bv_len; 468 } 469 470 if ( !BER_BVISNULL( &sub->sa_final ) ) { 471 if ( inlen > left.bv_len ) { 472 match = 1; 473 goto done; 474 } 475 476 match = memcmp( sub->sa_final.bv_val, 477 &left.bv_val[left.bv_len - sub->sa_final.bv_len], 478 sub->sa_final.bv_len ); 479 480 if ( match != 0 ) { 481 goto done; 482 } 483 484 left.bv_len -= sub->sa_final.bv_len; 485 inlen -= sub->sa_final.bv_len; 486 } 487 488 if ( sub->sa_any ) { 489 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 490 ber_len_t idx; 491 char *p; 492 493 retry: 494 if ( inlen > left.bv_len ) { 495 /* not enough length */ 496 match = 1; 497 goto done; 498 } 499 500 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) { 501 continue; 502 } 503 504 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len ); 505 506 if( p == NULL ) { 507 match = 1; 508 goto done; 509 } 510 511 idx = p - left.bv_val; 512 513 if ( idx >= left.bv_len ) { 514 /* this shouldn't happen */ 515 return LDAP_OTHER; 516 } 517 518 left.bv_val = p; 519 left.bv_len -= idx; 520 521 if ( sub->sa_any[i].bv_len > left.bv_len ) { 522 /* not enough left */ 523 match = 1; 524 goto done; 525 } 526 527 match = memcmp( left.bv_val, 528 sub->sa_any[i].bv_val, 529 sub->sa_any[i].bv_len ); 530 531 if ( match != 0 ) { 532 left.bv_val++; 533 left.bv_len--; 534 goto retry; 535 } 536 537 left.bv_val += sub->sa_any[i].bv_len; 538 left.bv_len -= sub->sa_any[i].bv_len; 539 inlen -= sub->sa_any[i].bv_len; 540 } 541 } 542 543 done: 544 *matchp = match; 545 return LDAP_SUCCESS; 546 } 547 548 /* Substrings Index generation function */ 549 static int 550 octetStringSubstringsIndexer( 551 slap_mask_t use, 552 slap_mask_t flags, 553 Syntax *syntax, 554 MatchingRule *mr, 555 struct berval *prefix, 556 BerVarray values, 557 BerVarray *keysp, 558 void *ctx ) 559 { 560 ber_len_t i, nkeys; 561 size_t slen, mlen; 562 BerVarray keys; 563 564 HASH_CONTEXT HCany, HCini, HCfin; 565 unsigned char HASHdigest[HASH_BYTES]; 566 struct berval digest; 567 digest.bv_val = (char *)HASHdigest; 568 digest.bv_len = sizeof(HASHdigest); 569 570 nkeys = 0; 571 572 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 573 /* count number of indices to generate */ 574 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) { 575 if( values[i].bv_len >= index_substr_if_maxlen ) { 576 nkeys += index_substr_if_maxlen - 577 (index_substr_if_minlen - 1); 578 } else if( values[i].bv_len >= index_substr_if_minlen ) { 579 nkeys += values[i].bv_len - (index_substr_if_minlen - 1); 580 } 581 } 582 583 if( flags & SLAP_INDEX_SUBSTR_ANY ) { 584 if( values[i].bv_len >= index_substr_any_len ) { 585 nkeys += values[i].bv_len - (index_substr_any_len - 1); 586 } 587 } 588 589 if( flags & SLAP_INDEX_SUBSTR_FINAL ) { 590 if( values[i].bv_len >= index_substr_if_maxlen ) { 591 nkeys += index_substr_if_maxlen - 592 (index_substr_if_minlen - 1); 593 } else if( values[i].bv_len >= index_substr_if_minlen ) { 594 nkeys += values[i].bv_len - (index_substr_if_minlen - 1); 595 } 596 } 597 } 598 599 if( nkeys == 0 ) { 600 /* no keys to generate */ 601 *keysp = NULL; 602 return LDAP_SUCCESS; 603 } 604 605 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx ); 606 607 slen = syntax->ssyn_oidlen; 608 mlen = mr->smr_oidlen; 609 610 if ( flags & SLAP_INDEX_SUBSTR_ANY ) 611 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr ); 612 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) 613 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr ); 614 if( flags & SLAP_INDEX_SUBSTR_FINAL ) 615 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr ); 616 617 nkeys = 0; 618 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 619 ber_len_t j,max; 620 621 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) && 622 ( values[i].bv_len >= index_substr_any_len ) ) 623 { 624 max = values[i].bv_len - (index_substr_any_len - 1); 625 626 for( j=0; j<max; j++ ) { 627 hashIter( &HCany, HASHdigest, 628 (unsigned char *)&values[i].bv_val[j], 629 index_substr_any_len ); 630 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 631 } 632 } 633 634 /* skip if too short */ 635 if( values[i].bv_len < index_substr_if_minlen ) continue; 636 637 max = index_substr_if_maxlen < values[i].bv_len 638 ? index_substr_if_maxlen : values[i].bv_len; 639 640 for( j=index_substr_if_minlen; j<=max; j++ ) { 641 642 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) { 643 hashIter( &HCini, HASHdigest, 644 (unsigned char *)values[i].bv_val, j ); 645 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 646 } 647 648 if( flags & SLAP_INDEX_SUBSTR_FINAL ) { 649 hashIter( &HCfin, HASHdigest, 650 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j ); 651 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 652 } 653 654 } 655 } 656 657 if( nkeys > 0 ) { 658 BER_BVZERO( &keys[nkeys] ); 659 *keysp = keys; 660 } else { 661 ch_free( keys ); 662 *keysp = NULL; 663 } 664 665 return LDAP_SUCCESS; 666 } 667 668 static int 669 octetStringSubstringsFilter ( 670 slap_mask_t use, 671 slap_mask_t flags, 672 Syntax *syntax, 673 MatchingRule *mr, 674 struct berval *prefix, 675 void * assertedValue, 676 BerVarray *keysp, 677 void *ctx) 678 { 679 SubstringsAssertion *sa; 680 char pre; 681 ber_len_t nkeys = 0; 682 size_t slen, mlen, klen; 683 BerVarray keys; 684 HASH_CONTEXT HASHcontext; 685 unsigned char HASHdigest[HASH_BYTES]; 686 struct berval *value; 687 struct berval digest; 688 689 sa = (SubstringsAssertion *) assertedValue; 690 691 if( flags & SLAP_INDEX_SUBSTR_INITIAL && 692 !BER_BVISNULL( &sa->sa_initial ) && 693 sa->sa_initial.bv_len >= index_substr_if_minlen ) 694 { 695 nkeys++; 696 if ( sa->sa_initial.bv_len > index_substr_if_maxlen && 697 ( flags & SLAP_INDEX_SUBSTR_ANY )) 698 { 699 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step; 700 } 701 } 702 703 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) { 704 ber_len_t i; 705 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) { 706 if( sa->sa_any[i].bv_len >= index_substr_any_len ) { 707 /* don't bother accounting with stepping */ 708 nkeys += sa->sa_any[i].bv_len - 709 ( index_substr_any_len - 1 ); 710 } 711 } 712 } 713 714 if( flags & SLAP_INDEX_SUBSTR_FINAL && 715 !BER_BVISNULL( &sa->sa_final ) && 716 sa->sa_final.bv_len >= index_substr_if_minlen ) 717 { 718 nkeys++; 719 if ( sa->sa_final.bv_len > index_substr_if_maxlen && 720 ( flags & SLAP_INDEX_SUBSTR_ANY )) 721 { 722 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; 723 } 724 } 725 726 if( nkeys == 0 ) { 727 *keysp = NULL; 728 return LDAP_SUCCESS; 729 } 730 731 digest.bv_val = (char *)HASHdigest; 732 digest.bv_len = sizeof(HASHdigest); 733 734 slen = syntax->ssyn_oidlen; 735 mlen = mr->smr_oidlen; 736 737 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx ); 738 nkeys = 0; 739 740 if( flags & SLAP_INDEX_SUBSTR_INITIAL && 741 !BER_BVISNULL( &sa->sa_initial ) && 742 sa->sa_initial.bv_len >= index_substr_if_minlen ) 743 { 744 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX; 745 value = &sa->sa_initial; 746 747 klen = index_substr_if_maxlen < value->bv_len 748 ? index_substr_if_maxlen : value->bv_len; 749 750 hashPreset( &HASHcontext, prefix, pre, syntax, mr ); 751 hashIter( &HASHcontext, HASHdigest, 752 (unsigned char *)value->bv_val, klen ); 753 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 754 755 /* If initial is too long and we have subany indexed, use it 756 * to match the excess... 757 */ 758 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY)) 759 { 760 ber_len_t j; 761 pre = SLAP_INDEX_SUBSTR_PREFIX; 762 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 763 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step ) 764 { 765 hashIter( &HASHcontext, HASHdigest, 766 (unsigned char *)&value->bv_val[j], index_substr_any_len ); 767 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 768 } 769 } 770 } 771 772 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) { 773 ber_len_t i, j; 774 pre = SLAP_INDEX_SUBSTR_PREFIX; 775 klen = index_substr_any_len; 776 777 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) { 778 if( sa->sa_any[i].bv_len < index_substr_any_len ) { 779 continue; 780 } 781 782 value = &sa->sa_any[i]; 783 784 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 785 for(j=0; 786 j <= value->bv_len - index_substr_any_len; 787 j += index_substr_any_step ) 788 { 789 hashIter( &HASHcontext, HASHdigest, 790 (unsigned char *)&value->bv_val[j], klen ); 791 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 792 } 793 } 794 } 795 796 if( flags & SLAP_INDEX_SUBSTR_FINAL && 797 !BER_BVISNULL( &sa->sa_final ) && 798 sa->sa_final.bv_len >= index_substr_if_minlen ) 799 { 800 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX; 801 value = &sa->sa_final; 802 803 klen = index_substr_if_maxlen < value->bv_len 804 ? index_substr_if_maxlen : value->bv_len; 805 806 hashPreset( &HASHcontext, prefix, pre, syntax, mr ); 807 hashIter( &HASHcontext, HASHdigest, 808 (unsigned char *)&value->bv_val[value->bv_len-klen], klen ); 809 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 810 811 /* If final is too long and we have subany indexed, use it 812 * to match the excess... 813 */ 814 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY)) 815 { 816 ber_len_t j; 817 pre = SLAP_INDEX_SUBSTR_PREFIX; 818 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 819 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step ) 820 { 821 hashIter( &HASHcontext, HASHdigest, 822 (unsigned char *)&value->bv_val[j], index_substr_any_len ); 823 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 824 } 825 } 826 } 827 828 if( nkeys > 0 ) { 829 BER_BVZERO( &keys[nkeys] ); 830 *keysp = keys; 831 } else { 832 ch_free( keys ); 833 *keysp = NULL; 834 } 835 836 return LDAP_SUCCESS; 837 } 838 839 static int 840 bitStringValidate( 841 Syntax *syntax, 842 struct berval *in ) 843 { 844 ber_len_t i; 845 846 /* very unforgiving validation, requires no normalization 847 * before simplistic matching 848 */ 849 if( in->bv_len < 3 ) { 850 return LDAP_INVALID_SYNTAX; 851 } 852 853 /* RFC 4517 Section 3.3.2 Bit String: 854 * BitString = SQUOTE *binary-digit SQUOTE "B" 855 * binary-digit = "0" / "1" 856 * 857 * where SQUOTE [RFC4512] is 858 * SQUOTE = %x27 ; single quote ("'") 859 * 860 * Example: '0101111101'B 861 */ 862 863 if( in->bv_val[0] != '\'' || 864 in->bv_val[in->bv_len - 2] != '\'' || 865 in->bv_val[in->bv_len - 1] != 'B' ) 866 { 867 return LDAP_INVALID_SYNTAX; 868 } 869 870 for( i = in->bv_len - 3; i > 0; i-- ) { 871 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) { 872 return LDAP_INVALID_SYNTAX; 873 } 874 } 875 876 return LDAP_SUCCESS; 877 } 878 879 /* 880 * Syntaxes from RFC 4517 881 * 882 883 3.3.2. Bit String 884 885 A value of the Bit String syntax is a sequence of binary digits. The 886 LDAP-specific encoding of a value of this syntax is defined by the 887 following ABNF: 888 889 BitString = SQUOTE *binary-digit SQUOTE "B" 890 891 binary-digit = "0" / "1" 892 893 The <SQUOTE> rule is defined in [MODELS]. 894 895 Example: 896 '0101111101'B 897 898 The LDAP definition for the Bit String syntax is: 899 900 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) 901 902 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1]. 903 904 ... 905 906 3.3.21. Name and Optional UID 907 908 A value of the Name and Optional UID syntax is the distinguished name 909 [MODELS] of an entity optionally accompanied by a unique identifier 910 that serves to differentiate the entity from others with an identical 911 distinguished name. 912 913 The LDAP-specific encoding of a value of this syntax is defined by 914 the following ABNF: 915 916 NameAndOptionalUID = distinguishedName [ SHARP BitString ] 917 918 The <BitString> rule is defined in Section 3.3.2. The 919 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is 920 defined in [MODELS]. 921 922 Note that although the '#' character may occur in the string 923 representation of a distinguished name, no additional escaping of 924 this character is performed when a <distinguishedName> is encoded in 925 a <NameAndOptionalUID>. 926 927 Example: 928 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B 929 930 The LDAP definition for the Name and Optional UID syntax is: 931 932 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' ) 933 934 This syntax corresponds to the NameAndOptionalUID ASN.1 type from 935 [X.520]. 936 937 * 938 * RFC 4512 says: 939 * 940 941 1.4. Common ABNF Productions 942 943 ... 944 SHARP = %x23 ; octothorpe (or sharp sign) ("#") 945 ... 946 SQUOTE = %x27 ; single quote ("'") 947 ... 948 949 * 950 * Note: normalization strips any leading "0"s, unless the 951 * bit string is exactly "'0'B", so the normalized example, 952 * in slapd, would result in 953 * 954 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B 955 * 956 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to 957 * be escaped except when at the beginning of a value, the 958 * definition of Name and Optional UID appears to be flawed, 959 * because there is no clear means to determine whether the 960 * UID part is present or not. 961 * 962 * Example: 963 * 964 * cn=Someone,dc=example,dc=com#'1'B 965 * 966 * could be either a NameAndOptionalUID with trailing UID, i.e. 967 * 968 * DN = "cn=Someone,dc=example,dc=com" 969 * UID = "'1'B" 970 * 971 * or a NameAndOptionalUID with no trailing UID, and the AVA 972 * in the last RDN made of 973 * 974 * attributeType = dc 975 * attributeValue = com#'1'B 976 * 977 * in fact "com#'1'B" is a valid IA5 string. 978 * 979 * As a consequence, current slapd code assumes that the 980 * presence of portions of a BitString at the end of the string 981 * representation of a NameAndOptionalUID means a BitString 982 * is expected, and cause an error otherwise. This is quite 983 * arbitrary, and might change in the future. 984 */ 985 986 987 static int 988 nameUIDValidate( 989 Syntax *syntax, 990 struct berval *in ) 991 { 992 int rc; 993 struct berval dn, uid; 994 995 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS; 996 997 ber_dupbv( &dn, in ); 998 if( !dn.bv_val ) return LDAP_OTHER; 999 1000 /* if there's a "#", try bitStringValidate()... */ 1001 uid.bv_val = strrchr( dn.bv_val, '#' ); 1002 if ( !BER_BVISNULL( &uid ) ) { 1003 uid.bv_val++; 1004 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val ); 1005 1006 rc = bitStringValidate( NULL, &uid ); 1007 if ( rc == LDAP_SUCCESS ) { 1008 /* in case of success, trim the UID, 1009 * otherwise treat it as part of the DN */ 1010 dn.bv_len -= uid.bv_len + 1; 1011 uid.bv_val[-1] = '\0'; 1012 } 1013 } 1014 1015 rc = dnValidate( NULL, &dn ); 1016 1017 ber_memfree( dn.bv_val ); 1018 return rc; 1019 } 1020 1021 int 1022 nameUIDPretty( 1023 Syntax *syntax, 1024 struct berval *val, 1025 struct berval *out, 1026 void *ctx ) 1027 { 1028 assert( val != NULL ); 1029 assert( out != NULL ); 1030 1031 1032 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 ); 1033 1034 if( BER_BVISEMPTY( val ) ) { 1035 ber_dupbv_x( out, val, ctx ); 1036 1037 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 1038 return LDAP_INVALID_SYNTAX; 1039 1040 } else { 1041 int rc; 1042 struct berval dnval = *val; 1043 struct berval uidval = BER_BVNULL; 1044 1045 uidval.bv_val = strrchr( val->bv_val, '#' ); 1046 if ( !BER_BVISNULL( &uidval ) ) { 1047 uidval.bv_val++; 1048 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val ); 1049 1050 rc = bitStringValidate( NULL, &uidval ); 1051 1052 if ( rc == LDAP_SUCCESS ) { 1053 ber_dupbv_x( &dnval, val, ctx ); 1054 dnval.bv_len -= uidval.bv_len + 1; 1055 dnval.bv_val[dnval.bv_len] = '\0'; 1056 1057 } else { 1058 BER_BVZERO( &uidval ); 1059 } 1060 } 1061 1062 rc = dnPretty( syntax, &dnval, out, ctx ); 1063 if ( dnval.bv_val != val->bv_val ) { 1064 slap_sl_free( dnval.bv_val, ctx ); 1065 } 1066 if( rc != LDAP_SUCCESS ) { 1067 return rc; 1068 } 1069 1070 if( !BER_BVISNULL( &uidval ) ) { 1071 int i, c, got1; 1072 char *tmp; 1073 1074 tmp = slap_sl_realloc( out->bv_val, out->bv_len 1075 + STRLENOF( "#" ) + uidval.bv_len + 1, 1076 ctx ); 1077 if( tmp == NULL ) { 1078 ber_memfree_x( out->bv_val, ctx ); 1079 return LDAP_OTHER; 1080 } 1081 out->bv_val = tmp; 1082 out->bv_val[out->bv_len++] = '#'; 1083 out->bv_val[out->bv_len++] = '\''; 1084 1085 got1 = uidval.bv_len < sizeof("'0'B"); 1086 for( i = 1; i < uidval.bv_len - 2; i++ ) { 1087 c = uidval.bv_val[i]; 1088 switch(c) { 1089 case '0': 1090 if( got1 ) out->bv_val[out->bv_len++] = c; 1091 break; 1092 case '1': 1093 got1 = 1; 1094 out->bv_val[out->bv_len++] = c; 1095 break; 1096 } 1097 } 1098 1099 out->bv_val[out->bv_len++] = '\''; 1100 out->bv_val[out->bv_len++] = 'B'; 1101 out->bv_val[out->bv_len] = '\0'; 1102 } 1103 } 1104 1105 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 ); 1106 1107 return LDAP_SUCCESS; 1108 } 1109 1110 static int 1111 uniqueMemberNormalize( 1112 slap_mask_t usage, 1113 Syntax *syntax, 1114 MatchingRule *mr, 1115 struct berval *val, 1116 struct berval *normalized, 1117 void *ctx ) 1118 { 1119 struct berval out; 1120 int rc; 1121 1122 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 1123 1124 ber_dupbv_x( &out, val, ctx ); 1125 if ( BER_BVISEMPTY( &out ) ) { 1126 *normalized = out; 1127 1128 } else { 1129 struct berval uid = BER_BVNULL; 1130 1131 uid.bv_val = strrchr( out.bv_val, '#' ); 1132 if ( !BER_BVISNULL( &uid ) ) { 1133 uid.bv_val++; 1134 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val ); 1135 1136 rc = bitStringValidate( NULL, &uid ); 1137 if ( rc == LDAP_SUCCESS ) { 1138 uid.bv_val[-1] = '\0'; 1139 out.bv_len -= uid.bv_len + 1; 1140 } else { 1141 BER_BVZERO( &uid ); 1142 } 1143 } 1144 1145 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx ); 1146 1147 if( rc != LDAP_SUCCESS ) { 1148 slap_sl_free( out.bv_val, ctx ); 1149 return LDAP_INVALID_SYNTAX; 1150 } 1151 1152 if( !BER_BVISNULL( &uid ) ) { 1153 char *tmp; 1154 1155 tmp = ch_realloc( normalized->bv_val, 1156 normalized->bv_len + uid.bv_len 1157 + STRLENOF("#") + 1 ); 1158 if ( tmp == NULL ) { 1159 ber_memfree_x( normalized->bv_val, ctx ); 1160 return LDAP_OTHER; 1161 } 1162 1163 normalized->bv_val = tmp; 1164 1165 /* insert the separator */ 1166 normalized->bv_val[normalized->bv_len++] = '#'; 1167 1168 /* append the UID */ 1169 AC_MEMCPY( &normalized->bv_val[normalized->bv_len], 1170 uid.bv_val, uid.bv_len ); 1171 normalized->bv_len += uid.bv_len; 1172 1173 /* terminate */ 1174 normalized->bv_val[normalized->bv_len] = '\0'; 1175 } 1176 1177 slap_sl_free( out.bv_val, ctx ); 1178 } 1179 1180 return LDAP_SUCCESS; 1181 } 1182 1183 static int 1184 uniqueMemberMatch( 1185 int *matchp, 1186 slap_mask_t flags, 1187 Syntax *syntax, 1188 MatchingRule *mr, 1189 struct berval *value, 1190 void *assertedValue ) 1191 { 1192 int match; 1193 struct berval *asserted = (struct berval *) assertedValue; 1194 struct berval assertedDN = *asserted; 1195 struct berval assertedUID = BER_BVNULL; 1196 struct berval valueDN = *value; 1197 struct berval valueUID = BER_BVNULL; 1198 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX); 1199 1200 if ( !BER_BVISEMPTY( asserted ) ) { 1201 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1202 if ( !BER_BVISNULL( &assertedUID ) ) { 1203 assertedUID.bv_val++; 1204 assertedUID.bv_len = assertedDN.bv_len 1205 - ( assertedUID.bv_val - assertedDN.bv_val ); 1206 1207 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1208 assertedDN.bv_len -= assertedUID.bv_len + 1; 1209 1210 } else { 1211 BER_BVZERO( &assertedUID ); 1212 } 1213 } 1214 } 1215 1216 if ( !BER_BVISEMPTY( value ) ) { 1217 1218 valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); 1219 if ( !BER_BVISNULL( &valueUID ) ) { 1220 valueUID.bv_val++; 1221 valueUID.bv_len = valueDN.bv_len 1222 - ( valueUID.bv_val - valueDN.bv_val ); 1223 1224 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) { 1225 valueDN.bv_len -= valueUID.bv_len + 1; 1226 1227 } else { 1228 BER_BVZERO( &valueUID ); 1229 } 1230 } 1231 } 1232 1233 if( valueUID.bv_len && assertedUID.bv_len ) { 1234 match = valueUID.bv_len - assertedUID.bv_len; 1235 if ( match ) { 1236 *matchp = match; 1237 return LDAP_SUCCESS; 1238 } 1239 1240 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len ); 1241 if( match ) { 1242 *matchp = match; 1243 return LDAP_SUCCESS; 1244 } 1245 1246 } else if ( !approx && valueUID.bv_len ) { 1247 match = -1; 1248 *matchp = match; 1249 return LDAP_SUCCESS; 1250 1251 } else if ( !approx && assertedUID.bv_len ) { 1252 match = 1; 1253 *matchp = match; 1254 return LDAP_SUCCESS; 1255 } 1256 1257 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN ); 1258 } 1259 1260 static int 1261 uniqueMemberIndexer( 1262 slap_mask_t use, 1263 slap_mask_t flags, 1264 Syntax *syntax, 1265 MatchingRule *mr, 1266 struct berval *prefix, 1267 BerVarray values, 1268 BerVarray *keysp, 1269 void *ctx ) 1270 { 1271 BerVarray dnvalues; 1272 int rc; 1273 int i; 1274 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 1275 /* just count them */ 1276 } 1277 assert( i > 0 ); 1278 1279 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 1280 1281 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 1282 struct berval assertedDN = values[i]; 1283 struct berval assertedUID = BER_BVNULL; 1284 1285 if ( !BER_BVISEMPTY( &assertedDN ) ) { 1286 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1287 if ( !BER_BVISNULL( &assertedUID ) ) { 1288 assertedUID.bv_val++; 1289 assertedUID.bv_len = assertedDN.bv_len 1290 - ( assertedUID.bv_val - assertedDN.bv_val ); 1291 1292 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1293 assertedDN.bv_len -= assertedUID.bv_len + 1; 1294 1295 } else { 1296 BER_BVZERO( &assertedUID ); 1297 } 1298 } 1299 } 1300 1301 dnvalues[i] = assertedDN; 1302 } 1303 BER_BVZERO( &dnvalues[i] ); 1304 1305 rc = octetStringIndexer( use, flags, syntax, mr, prefix, 1306 dnvalues, keysp, ctx ); 1307 1308 slap_sl_free( dnvalues, ctx ); 1309 return rc; 1310 } 1311 1312 static int 1313 uniqueMemberFilter( 1314 slap_mask_t use, 1315 slap_mask_t flags, 1316 Syntax *syntax, 1317 MatchingRule *mr, 1318 struct berval *prefix, 1319 void * assertedValue, 1320 BerVarray *keysp, 1321 void *ctx ) 1322 { 1323 struct berval *asserted = (struct berval *) assertedValue; 1324 struct berval assertedDN = *asserted; 1325 struct berval assertedUID = BER_BVNULL; 1326 1327 if ( !BER_BVISEMPTY( asserted ) ) { 1328 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1329 if ( !BER_BVISNULL( &assertedUID ) ) { 1330 assertedUID.bv_val++; 1331 assertedUID.bv_len = assertedDN.bv_len 1332 - ( assertedUID.bv_val - assertedDN.bv_val ); 1333 1334 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1335 assertedDN.bv_len -= assertedUID.bv_len + 1; 1336 1337 } else { 1338 BER_BVZERO( &assertedUID ); 1339 } 1340 } 1341 } 1342 1343 return octetStringFilter( use, flags, syntax, mr, prefix, 1344 &assertedDN, keysp, ctx ); 1345 } 1346 1347 1348 /* 1349 * Handling boolean syntax and matching is quite rigid. 1350 * A more flexible approach would be to allow a variety 1351 * of strings to be normalized and prettied into TRUE 1352 * and FALSE. 1353 */ 1354 static int 1355 booleanValidate( 1356 Syntax *syntax, 1357 struct berval *in ) 1358 { 1359 /* very unforgiving validation, requires no normalization 1360 * before simplistic matching 1361 */ 1362 1363 if( in->bv_len == 4 ) { 1364 if( bvmatch( in, &slap_true_bv ) ) { 1365 return LDAP_SUCCESS; 1366 } 1367 } else if( in->bv_len == 5 ) { 1368 if( bvmatch( in, &slap_false_bv ) ) { 1369 return LDAP_SUCCESS; 1370 } 1371 } 1372 1373 return LDAP_INVALID_SYNTAX; 1374 } 1375 1376 static int 1377 booleanMatch( 1378 int *matchp, 1379 slap_mask_t flags, 1380 Syntax *syntax, 1381 MatchingRule *mr, 1382 struct berval *value, 1383 void *assertedValue ) 1384 { 1385 /* simplistic matching allowed by rigid validation */ 1386 struct berval *asserted = (struct berval *) assertedValue; 1387 *matchp = value->bv_len != asserted->bv_len; 1388 return LDAP_SUCCESS; 1389 } 1390 1391 /*------------------------------------------------------------------- 1392 LDAP/X.500 string syntax / matching rules have a few oddities. This 1393 comment attempts to detail how slapd(8) treats them. 1394 1395 Summary: 1396 StringSyntax X.500 LDAP Matching/Comments 1397 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces 1398 PrintableString subset subset i/e + ignore insignificant spaces 1399 PrintableString subset subset i/e + ignore insignificant spaces 1400 NumericString subset subset ignore all spaces 1401 IA5String ASCII ASCII i/e + ignore insignificant spaces 1402 TeletexString T.61 T.61 i/e + ignore insignificant spaces 1403 1404 TelephoneNumber subset subset i + ignore all spaces and "-" 1405 1406 See RFC 4518 for details. 1407 1408 1409 Directory String - 1410 In X.500(93), a directory string can be either a PrintableString, 1411 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)). 1412 In later versions, more CHOICEs were added. In all cases the string 1413 must be non-empty. 1414 1415 In LDAPv3, a directory string is a UTF-8 encoded UCS string. 1416 A directory string cannot be zero length. 1417 1418 For matching, there are both case ignore and exact rules. Both 1419 also require that "insignificant" spaces be ignored. 1420 spaces before the first non-space are ignored; 1421 spaces after the last non-space are ignored; 1422 spaces after a space are ignored. 1423 Note: by these rules (and as clarified in X.520), a string of only 1424 spaces is to be treated as if held one space, not empty (which 1425 would be a syntax error). 1426 1427 NumericString 1428 In ASN.1, numeric string is just a string of digits and spaces 1429 and could be empty. However, in X.500, all attribute values of 1430 numeric string carry a non-empty constraint. For example: 1431 1432 internationalISDNNumber ATTRIBUTE ::= { 1433 WITH SYNTAX InternationalISDNNumber 1434 EQUALITY MATCHING RULE numericStringMatch 1435 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch 1436 ID id-at-internationalISDNNumber } 1437 InternationalISDNNumber ::= 1438 NumericString (SIZE(1..ub-international-isdn-number)) 1439 1440 Unforunately, some assertion values are don't carry the same 1441 constraint (but its unclear how such an assertion could ever 1442 be true). In LDAP, there is one syntax (numericString) not two 1443 (numericString with constraint, numericString without constraint). 1444 This should be treated as numericString with non-empty constraint. 1445 Note that while someone may have no ISDN number, there are no ISDN 1446 numbers which are zero length. 1447 1448 In matching, spaces are ignored. 1449 1450 PrintableString 1451 In ASN.1, Printable string is just a string of printable characters 1452 and can be empty. In X.500, semantics much like NumericString (see 1453 serialNumber for a like example) excepting uses insignificant space 1454 handling instead of ignore all spaces. They must be non-empty. 1455 1456 IA5String 1457 Basically same as PrintableString. There are no examples in X.500, 1458 but same logic applies. Empty strings are allowed. 1459 1460 -------------------------------------------------------------------*/ 1461 1462 static int 1463 UTF8StringValidate( 1464 Syntax *syntax, 1465 struct berval *in ) 1466 { 1467 ber_len_t count; 1468 int len; 1469 unsigned char *u = (unsigned char *)in->bv_val; 1470 1471 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) { 1472 /* directory strings cannot be empty */ 1473 return LDAP_INVALID_SYNTAX; 1474 } 1475 1476 for( count = in->bv_len; count > 0; count -= len, u += len ) { 1477 /* get the length indicated by the first byte */ 1478 len = LDAP_UTF8_CHARLEN2( u, len ); 1479 1480 /* very basic checks */ 1481 switch( len ) { 1482 case 6: 1483 if( (u[5] & 0xC0) != 0x80 ) { 1484 return LDAP_INVALID_SYNTAX; 1485 } 1486 case 5: 1487 if( (u[4] & 0xC0) != 0x80 ) { 1488 return LDAP_INVALID_SYNTAX; 1489 } 1490 case 4: 1491 if( (u[3] & 0xC0) != 0x80 ) { 1492 return LDAP_INVALID_SYNTAX; 1493 } 1494 case 3: 1495 if( (u[2] & 0xC0 )!= 0x80 ) { 1496 return LDAP_INVALID_SYNTAX; 1497 } 1498 case 2: 1499 if( (u[1] & 0xC0) != 0x80 ) { 1500 return LDAP_INVALID_SYNTAX; 1501 } 1502 case 1: 1503 /* CHARLEN already validated it */ 1504 break; 1505 default: 1506 return LDAP_INVALID_SYNTAX; 1507 } 1508 1509 /* make sure len corresponds with the offset 1510 to the next character */ 1511 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX; 1512 } 1513 1514 if( count != 0 ) { 1515 return LDAP_INVALID_SYNTAX; 1516 } 1517 1518 return LDAP_SUCCESS; 1519 } 1520 1521 static int 1522 UTF8StringNormalize( 1523 slap_mask_t use, 1524 Syntax *syntax, 1525 MatchingRule *mr, 1526 struct berval *val, 1527 struct berval *normalized, 1528 void *ctx ) 1529 { 1530 struct berval tmp, nvalue; 1531 int flags; 1532 int i, wasspace; 1533 1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 1535 1536 if( BER_BVISNULL( val ) ) { 1537 /* assume we're dealing with a syntax (e.g., UTF8String) 1538 * which allows empty strings 1539 */ 1540 BER_BVZERO( normalized ); 1541 return LDAP_SUCCESS; 1542 } 1543 1544 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch ) 1545 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD; 1546 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX ) 1547 ? LDAP_UTF8_APPROX : 0; 1548 1549 val = UTF8bvnormalize( val, &tmp, flags, ctx ); 1550 if( val == NULL ) { 1551 return LDAP_OTHER; 1552 } 1553 1554 /* collapse spaces (in place) */ 1555 nvalue.bv_len = 0; 1556 nvalue.bv_val = tmp.bv_val; 1557 1558 /* trim leading spaces? */ 1559 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) || 1560 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL )); 1561 1562 for( i = 0; i < tmp.bv_len; i++) { 1563 if ( ASCII_SPACE( tmp.bv_val[i] )) { 1564 if( wasspace++ == 0 ) { 1565 /* trim repeated spaces */ 1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i]; 1567 } 1568 } else { 1569 wasspace = 0; 1570 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i]; 1571 } 1572 } 1573 1574 if( !BER_BVISEMPTY( &nvalue ) ) { 1575 /* trim trailing space? */ 1576 if( wasspace && ( 1577 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) && 1578 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY )) 1579 { 1580 --nvalue.bv_len; 1581 } 1582 nvalue.bv_val[nvalue.bv_len] = '\0'; 1583 1584 } else { 1585 /* string of all spaces is treated as one space */ 1586 nvalue.bv_val[0] = ' '; 1587 nvalue.bv_val[1] = '\0'; 1588 nvalue.bv_len = 1; 1589 } 1590 1591 *normalized = nvalue; 1592 return LDAP_SUCCESS; 1593 } 1594 1595 static int 1596 directoryStringSubstringsMatch( 1597 int *matchp, 1598 slap_mask_t flags, 1599 Syntax *syntax, 1600 MatchingRule *mr, 1601 struct berval *value, 1602 void *assertedValue ) 1603 { 1604 int match = 0; 1605 SubstringsAssertion *sub = assertedValue; 1606 struct berval left = *value; 1607 int i; 1608 int priorspace=0; 1609 1610 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 1611 if ( sub->sa_initial.bv_len > left.bv_len ) { 1612 /* not enough left */ 1613 match = 1; 1614 goto done; 1615 } 1616 1617 match = memcmp( sub->sa_initial.bv_val, left.bv_val, 1618 sub->sa_initial.bv_len ); 1619 1620 if ( match != 0 ) { 1621 goto done; 1622 } 1623 1624 left.bv_val += sub->sa_initial.bv_len; 1625 left.bv_len -= sub->sa_initial.bv_len; 1626 1627 priorspace = ASCII_SPACE( 1628 sub->sa_initial.bv_val[sub->sa_initial.bv_len] ); 1629 } 1630 1631 if ( sub->sa_any ) { 1632 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 1633 ber_len_t idx; 1634 char *p; 1635 1636 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] ) 1637 && ASCII_SPACE( sub->sa_any[i].bv_val[0] )) 1638 { 1639 /* allow next space to match */ 1640 left.bv_val--; 1641 left.bv_len++; 1642 } 1643 priorspace=0; 1644 1645 retry: 1646 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) { 1647 continue; 1648 } 1649 1650 if ( sub->sa_any[i].bv_len > left.bv_len ) { 1651 /* not enough left */ 1652 match = 1; 1653 goto done; 1654 } 1655 1656 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len ); 1657 1658 if( p == NULL ) { 1659 match = 1; 1660 goto done; 1661 } 1662 1663 idx = p - left.bv_val; 1664 1665 if ( idx >= left.bv_len ) { 1666 /* this shouldn't happen */ 1667 return LDAP_OTHER; 1668 } 1669 1670 left.bv_val = p; 1671 left.bv_len -= idx; 1672 1673 if ( sub->sa_any[i].bv_len > left.bv_len ) { 1674 /* not enough left */ 1675 match = 1; 1676 goto done; 1677 } 1678 1679 match = memcmp( left.bv_val, 1680 sub->sa_any[i].bv_val, 1681 sub->sa_any[i].bv_len ); 1682 1683 if ( match != 0 ) { 1684 left.bv_val++; 1685 left.bv_len--; 1686 goto retry; 1687 } 1688 1689 left.bv_val += sub->sa_any[i].bv_len; 1690 left.bv_len -= sub->sa_any[i].bv_len; 1691 1692 priorspace = ASCII_SPACE( 1693 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] ); 1694 } 1695 } 1696 1697 if ( !BER_BVISNULL( &sub->sa_final ) ) { 1698 if( priorspace && !BER_BVISEMPTY( &sub->sa_final ) 1699 && ASCII_SPACE( sub->sa_final.bv_val[0] )) 1700 { 1701 /* allow next space to match */ 1702 left.bv_val--; 1703 left.bv_len++; 1704 } 1705 1706 if ( sub->sa_final.bv_len > left.bv_len ) { 1707 /* not enough left */ 1708 match = 1; 1709 goto done; 1710 } 1711 1712 match = memcmp( sub->sa_final.bv_val, 1713 &left.bv_val[left.bv_len - sub->sa_final.bv_len], 1714 sub->sa_final.bv_len ); 1715 1716 if ( match != 0 ) { 1717 goto done; 1718 } 1719 } 1720 1721 done: 1722 *matchp = match; 1723 return LDAP_SUCCESS; 1724 } 1725 1726 #if defined(SLAPD_APPROX_INITIALS) 1727 # define SLAPD_APPROX_DELIMITER "._ " 1728 # define SLAPD_APPROX_WORDLEN 2 1729 #else 1730 # define SLAPD_APPROX_DELIMITER " " 1731 # define SLAPD_APPROX_WORDLEN 1 1732 #endif 1733 1734 static int 1735 approxMatch( 1736 int *matchp, 1737 slap_mask_t flags, 1738 Syntax *syntax, 1739 MatchingRule *mr, 1740 struct berval *value, 1741 void *assertedValue ) 1742 { 1743 struct berval *nval, *assertv; 1744 char *val, **values, **words, *c; 1745 int i, count, len, nextchunk=0, nextavail=0; 1746 1747 /* Yes, this is necessary */ 1748 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL ); 1749 if( nval == NULL ) { 1750 *matchp = 1; 1751 return LDAP_SUCCESS; 1752 } 1753 1754 /* Yes, this is necessary */ 1755 assertv = UTF8bvnormalize( ((struct berval *)assertedValue), 1756 NULL, LDAP_UTF8_APPROX, NULL ); 1757 if( assertv == NULL ) { 1758 ber_bvfree( nval ); 1759 *matchp = 1; 1760 return LDAP_SUCCESS; 1761 } 1762 1763 /* Isolate how many words there are */ 1764 for ( c = nval->bv_val, count = 1; *c; c++ ) { 1765 c = strpbrk( c, SLAPD_APPROX_DELIMITER ); 1766 if ( c == NULL ) break; 1767 *c = '\0'; 1768 count++; 1769 } 1770 1771 /* Get a phonetic copy of each word */ 1772 words = (char **)ch_malloc( count * sizeof(char *) ); 1773 values = (char **)ch_malloc( count * sizeof(char *) ); 1774 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) { 1775 words[i] = c; 1776 values[i] = phonetic(c); 1777 } 1778 1779 /* Work through the asserted value's words, to see if at least some 1780 of the words are there, in the same order. */ 1781 len = 0; 1782 while ( (ber_len_t) nextchunk < assertv->bv_len ) { 1783 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER); 1784 if( len == 0 ) { 1785 nextchunk++; 1786 continue; 1787 } 1788 #if defined(SLAPD_APPROX_INITIALS) 1789 else if( len == 1 ) { 1790 /* Single letter words need to at least match one word's initial */ 1791 for( i=nextavail; i<count; i++ ) 1792 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) { 1793 nextavail=i+1; 1794 break; 1795 } 1796 } 1797 #endif 1798 else { 1799 /* Isolate the next word in the asserted value and phonetic it */ 1800 assertv->bv_val[nextchunk+len] = '\0'; 1801 val = phonetic( assertv->bv_val + nextchunk ); 1802 1803 /* See if this phonetic chunk is in the remaining words of *value */ 1804 for( i=nextavail; i<count; i++ ){ 1805 if( !strcmp( val, values[i] ) ){ 1806 nextavail = i+1; 1807 break; 1808 } 1809 } 1810 ch_free( val ); 1811 } 1812 1813 /* This chunk in the asserted value was NOT within the *value. */ 1814 if( i >= count ) { 1815 nextavail=-1; 1816 break; 1817 } 1818 1819 /* Go on to the next word in the asserted value */ 1820 nextchunk += len+1; 1821 } 1822 1823 /* If some of the words were seen, call it a match */ 1824 if( nextavail > 0 ) { 1825 *matchp = 0; 1826 } 1827 else { 1828 *matchp = 1; 1829 } 1830 1831 /* Cleanup allocs */ 1832 ber_bvfree( assertv ); 1833 for( i=0; i<count; i++ ) { 1834 ch_free( values[i] ); 1835 } 1836 ch_free( values ); 1837 ch_free( words ); 1838 ber_bvfree( nval ); 1839 1840 return LDAP_SUCCESS; 1841 } 1842 1843 static int 1844 approxIndexer( 1845 slap_mask_t use, 1846 slap_mask_t flags, 1847 Syntax *syntax, 1848 MatchingRule *mr, 1849 struct berval *prefix, 1850 BerVarray values, 1851 BerVarray *keysp, 1852 void *ctx ) 1853 { 1854 char *c; 1855 int i,j, len, wordcount, keycount=0; 1856 struct berval *newkeys; 1857 BerVarray keys=NULL; 1858 1859 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) { 1860 struct berval val = BER_BVNULL; 1861 /* Yes, this is necessary */ 1862 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL ); 1863 assert( !BER_BVISNULL( &val ) ); 1864 1865 /* Isolate how many words there are. There will be a key for each */ 1866 for( wordcount = 0, c = val.bv_val; *c; c++) { 1867 len = strcspn(c, SLAPD_APPROX_DELIMITER); 1868 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++; 1869 c+= len; 1870 if (*c == '\0') break; 1871 *c = '\0'; 1872 } 1873 1874 /* Allocate/increase storage to account for new keys */ 1875 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1) 1876 * sizeof(struct berval) ); 1877 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) ); 1878 if( keys ) ch_free( keys ); 1879 keys = newkeys; 1880 1881 /* Get a phonetic copy of each word */ 1882 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) { 1883 len = strlen( c ); 1884 if( len < SLAPD_APPROX_WORDLEN ) continue; 1885 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] ); 1886 keycount++; 1887 i++; 1888 } 1889 1890 ber_memfree( val.bv_val ); 1891 } 1892 BER_BVZERO( &keys[keycount] ); 1893 *keysp = keys; 1894 1895 return LDAP_SUCCESS; 1896 } 1897 1898 static int 1899 approxFilter( 1900 slap_mask_t use, 1901 slap_mask_t flags, 1902 Syntax *syntax, 1903 MatchingRule *mr, 1904 struct berval *prefix, 1905 void * assertedValue, 1906 BerVarray *keysp, 1907 void *ctx ) 1908 { 1909 char *c; 1910 int i, count, len; 1911 struct berval *val; 1912 BerVarray keys; 1913 1914 /* Yes, this is necessary */ 1915 val = UTF8bvnormalize( ((struct berval *)assertedValue), 1916 NULL, LDAP_UTF8_APPROX, NULL ); 1917 if( val == NULL || BER_BVISNULL( val ) ) { 1918 keys = (struct berval *)ch_malloc( sizeof(struct berval) ); 1919 BER_BVZERO( &keys[0] ); 1920 *keysp = keys; 1921 ber_bvfree( val ); 1922 return LDAP_SUCCESS; 1923 } 1924 1925 /* Isolate how many words there are. There will be a key for each */ 1926 for( count = 0,c = val->bv_val; *c; c++) { 1927 len = strcspn(c, SLAPD_APPROX_DELIMITER); 1928 if( len >= SLAPD_APPROX_WORDLEN ) count++; 1929 c+= len; 1930 if (*c == '\0') break; 1931 *c = '\0'; 1932 } 1933 1934 /* Allocate storage for new keys */ 1935 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) ); 1936 1937 /* Get a phonetic copy of each word */ 1938 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) { 1939 len = strlen(c); 1940 if( len < SLAPD_APPROX_WORDLEN ) continue; 1941 ber_str2bv( phonetic( c ), 0, 0, &keys[i] ); 1942 i++; 1943 } 1944 1945 ber_bvfree( val ); 1946 1947 BER_BVZERO( &keys[count] ); 1948 *keysp = keys; 1949 1950 return LDAP_SUCCESS; 1951 } 1952 1953 /* Remove all spaces and '-' characters */ 1954 static int 1955 telephoneNumberNormalize( 1956 slap_mask_t usage, 1957 Syntax *syntax, 1958 MatchingRule *mr, 1959 struct berval *val, 1960 struct berval *normalized, 1961 void *ctx ) 1962 { 1963 char *p, *q; 1964 1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 1966 1967 /* validator should have refused an empty string */ 1968 assert( !BER_BVISEMPTY( val ) ); 1969 1970 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 1971 1972 for( p = val->bv_val; *p; p++ ) { 1973 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) { 1974 *q++ = *p; 1975 } 1976 } 1977 *q = '\0'; 1978 1979 normalized->bv_len = q - normalized->bv_val; 1980 1981 if( BER_BVISEMPTY( normalized ) ) { 1982 slap_sl_free( normalized->bv_val, ctx ); 1983 BER_BVZERO( normalized ); 1984 return LDAP_INVALID_SYNTAX; 1985 } 1986 1987 return LDAP_SUCCESS; 1988 } 1989 1990 int 1991 numericoidValidate( 1992 Syntax *syntax, 1993 struct berval *in ) 1994 { 1995 struct berval val = *in; 1996 1997 if( BER_BVISEMPTY( &val ) ) { 1998 /* disallow empty strings */ 1999 return LDAP_INVALID_SYNTAX; 2000 } 2001 2002 while( OID_LEADCHAR( val.bv_val[0] ) ) { 2003 if ( val.bv_len == 1 ) { 2004 return LDAP_SUCCESS; 2005 } 2006 2007 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) { 2008 break; 2009 } 2010 2011 val.bv_val++; 2012 val.bv_len--; 2013 2014 while ( OID_LEADCHAR( val.bv_val[0] )) { 2015 val.bv_val++; 2016 val.bv_len--; 2017 2018 if ( val.bv_len == 0 ) { 2019 return LDAP_SUCCESS; 2020 } 2021 } 2022 2023 if( !OID_SEPARATOR( val.bv_val[0] )) { 2024 break; 2025 } 2026 2027 val.bv_val++; 2028 val.bv_len--; 2029 } 2030 2031 return LDAP_INVALID_SYNTAX; 2032 } 2033 2034 static int 2035 integerValidate( 2036 Syntax *syntax, 2037 struct berval *in ) 2038 { 2039 ber_len_t i; 2040 struct berval val = *in; 2041 2042 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX; 2043 2044 if ( val.bv_val[0] == '-' ) { 2045 val.bv_len--; 2046 val.bv_val++; 2047 2048 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */ 2049 return LDAP_INVALID_SYNTAX; 2050 } 2051 2052 if( val.bv_val[0] == '0' ) { /* "-0" */ 2053 return LDAP_INVALID_SYNTAX; 2054 } 2055 2056 } else if ( val.bv_val[0] == '0' ) { 2057 if( val.bv_len > 1 ) { /* "0<more>" */ 2058 return LDAP_INVALID_SYNTAX; 2059 } 2060 2061 return LDAP_SUCCESS; 2062 } 2063 2064 for( i=0; i < val.bv_len; i++ ) { 2065 if( !ASCII_DIGIT(val.bv_val[i]) ) { 2066 return LDAP_INVALID_SYNTAX; 2067 } 2068 } 2069 2070 return LDAP_SUCCESS; 2071 } 2072 2073 static int 2074 integerMatch( 2075 int *matchp, 2076 slap_mask_t flags, 2077 Syntax *syntax, 2078 MatchingRule *mr, 2079 struct berval *value, 2080 void *assertedValue ) 2081 { 2082 struct berval *asserted = (struct berval *) assertedValue; 2083 int vsign = 1, asign = 1; /* default sign = '+' */ 2084 struct berval v, a; 2085 int match; 2086 2087 v = *value; 2088 if( v.bv_val[0] == '-' ) { 2089 vsign = -1; 2090 v.bv_val++; 2091 v.bv_len--; 2092 } 2093 2094 if( BER_BVISEMPTY( &v ) ) vsign = 0; 2095 2096 a = *asserted; 2097 if( a.bv_val[0] == '-' ) { 2098 asign = -1; 2099 a.bv_val++; 2100 a.bv_len--; 2101 } 2102 2103 if( BER_BVISEMPTY( &a ) ) vsign = 0; 2104 2105 match = vsign - asign; 2106 if( match == 0 ) { 2107 match = ( v.bv_len != a.bv_len 2108 ? ( v.bv_len < a.bv_len ? -1 : 1 ) 2109 : memcmp( v.bv_val, a.bv_val, v.bv_len )); 2110 if( vsign < 0 ) match = -match; 2111 } 2112 2113 *matchp = match; 2114 return LDAP_SUCCESS; 2115 } 2116 2117 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */ 2118 #define INDEX_INTLEN_CHOP 7 2119 #define INDEX_INTLEN_CHOPBYTES 3 2120 2121 static int 2122 integerVal2Key( 2123 struct berval *in, 2124 struct berval *key, 2125 struct berval *tmp, 2126 void *ctx ) 2127 { 2128 /* index format: 2129 * only if too large: one's complement <sign*exponent (chopped bytes)>, 2130 * two's complement value (sign-extended or chopped as needed), 2131 * however the top <number of exponent-bytes + 1> bits of first byte 2132 * above is the inverse sign. The next bit is the sign as delimiter. 2133 */ 2134 ber_slen_t k = index_intlen_strlen; 2135 ber_len_t chop = 0; 2136 unsigned signmask = ~0x7fU; 2137 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff; 2138 struct berval val = *in, itmp = *tmp; 2139 2140 if ( val.bv_val[0] != '-' ) { 2141 neg = 0; 2142 --k; 2143 } 2144 2145 /* Chop least significant digits, increase length instead */ 2146 if ( val.bv_len > (ber_len_t) k ) { 2147 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */ 2148 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */ 2149 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */ 2150 } 2151 2152 if ( lutil_str2bin( &val, &itmp, ctx )) { 2153 return LDAP_INVALID_SYNTAX; 2154 } 2155 2156 /* Omit leading sign byte */ 2157 if ( itmp.bv_val[0] == neg ) { 2158 itmp.bv_val++; 2159 itmp.bv_len--; 2160 } 2161 2162 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop); 2163 if ( k > 0 ) { 2164 assert( chop == 0 ); 2165 memset( key->bv_val, neg, k ); /* sign-extend */ 2166 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) { 2167 lenp = lenbuf + sizeof(lenbuf); 2168 chop = - (ber_len_t) k; 2169 do { 2170 *--lenp = ((unsigned char) chop & 0xff) ^ neg; 2171 signmask >>= 1; 2172 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) ); 2173 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff) 2174 * are 1, and the top n+2 bits of lenp[] are the sign bit. */ 2175 k = (lenbuf + sizeof(lenbuf)) - lenp; 2176 if ( k > (ber_slen_t) index_intlen ) 2177 k = index_intlen; 2178 memcpy( key->bv_val, lenp, k ); 2179 itmp.bv_len = index_intlen - k; 2180 } 2181 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len ); 2182 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */ 2183 return 0; 2184 } 2185 2186 /* Index generation function */ 2187 static int 2188 integerIndexer( 2189 slap_mask_t use, 2190 slap_mask_t flags, 2191 Syntax *syntax, 2192 MatchingRule *mr, 2193 struct berval *prefix, 2194 BerVarray values, 2195 BerVarray *keysp, 2196 void *ctx ) 2197 { 2198 char ibuf[64]; 2199 struct berval itmp; 2200 BerVarray keys; 2201 ber_len_t vlen; 2202 int i, rc; 2203 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2204 2205 /* count the values and find max needed length */ 2206 vlen = 0; 2207 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2208 if ( vlen < values[i].bv_len ) 2209 vlen = values[i].bv_len; 2210 } 2211 if ( vlen > maxstrlen ) 2212 vlen = maxstrlen; 2213 2214 /* we should have at least one value at this point */ 2215 assert( i > 0 ); 2216 2217 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 2218 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2219 keys[i].bv_len = index_intlen; 2220 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx ); 2221 } 2222 keys[i].bv_len = 0; 2223 keys[i].bv_val = NULL; 2224 2225 if ( vlen > sizeof(ibuf) ) { 2226 itmp.bv_val = slap_sl_malloc( vlen, ctx ); 2227 } else { 2228 itmp.bv_val = ibuf; 2229 } 2230 itmp.bv_len = sizeof(ibuf); 2231 2232 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 2233 if ( itmp.bv_val != ibuf ) { 2234 itmp.bv_len = values[i].bv_len; 2235 if ( itmp.bv_len <= sizeof(ibuf) ) 2236 itmp.bv_len = sizeof(ibuf); 2237 else if ( itmp.bv_len > maxstrlen ) 2238 itmp.bv_len = maxstrlen; 2239 } 2240 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx ); 2241 if ( rc ) 2242 goto func_leave; 2243 } 2244 *keysp = keys; 2245 func_leave: 2246 if ( itmp.bv_val != ibuf ) { 2247 slap_sl_free( itmp.bv_val, ctx ); 2248 } 2249 return rc; 2250 } 2251 2252 /* Index generation function */ 2253 static int 2254 integerFilter( 2255 slap_mask_t use, 2256 slap_mask_t flags, 2257 Syntax *syntax, 2258 MatchingRule *mr, 2259 struct berval *prefix, 2260 void * assertedValue, 2261 BerVarray *keysp, 2262 void *ctx ) 2263 { 2264 char ibuf[64]; 2265 struct berval iv; 2266 BerVarray keys; 2267 struct berval *value; 2268 int rc; 2269 2270 value = (struct berval *) assertedValue; 2271 2272 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 2273 2274 keys[0].bv_len = index_intlen; 2275 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx ); 2276 2277 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1 2278 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2279 if ( iv.bv_len > (int) sizeof(ibuf) ) { 2280 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx ); 2281 } else { 2282 iv.bv_val = ibuf; 2283 iv.bv_len = sizeof(ibuf); 2284 } 2285 2286 rc = integerVal2Key( value, keys, &iv, ctx ); 2287 if ( rc == 0 ) 2288 *keysp = keys; 2289 2290 if ( iv.bv_val != ibuf ) { 2291 slap_sl_free( iv.bv_val, ctx ); 2292 } 2293 return rc; 2294 } 2295 2296 static int 2297 countryStringValidate( 2298 Syntax *syntax, 2299 struct berval *val ) 2300 { 2301 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX; 2302 2303 if( !SLAP_PRINTABLE(val->bv_val[0]) ) { 2304 return LDAP_INVALID_SYNTAX; 2305 } 2306 if( !SLAP_PRINTABLE(val->bv_val[1]) ) { 2307 return LDAP_INVALID_SYNTAX; 2308 } 2309 2310 return LDAP_SUCCESS; 2311 } 2312 2313 static int 2314 printableStringValidate( 2315 Syntax *syntax, 2316 struct berval *val ) 2317 { 2318 ber_len_t i; 2319 2320 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2321 2322 for(i=0; i < val->bv_len; i++) { 2323 if( !SLAP_PRINTABLE(val->bv_val[i]) ) { 2324 return LDAP_INVALID_SYNTAX; 2325 } 2326 } 2327 2328 return LDAP_SUCCESS; 2329 } 2330 2331 static int 2332 printablesStringValidate( 2333 Syntax *syntax, 2334 struct berval *val ) 2335 { 2336 ber_len_t i, len; 2337 2338 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2339 2340 for(i=0,len=0; i < val->bv_len; i++) { 2341 int c = val->bv_val[i]; 2342 2343 if( c == '$' ) { 2344 if( len == 0 ) { 2345 return LDAP_INVALID_SYNTAX; 2346 } 2347 len = 0; 2348 2349 } else if ( SLAP_PRINTABLE(c) ) { 2350 len++; 2351 } else { 2352 return LDAP_INVALID_SYNTAX; 2353 } 2354 } 2355 2356 if( len == 0 ) { 2357 return LDAP_INVALID_SYNTAX; 2358 } 2359 2360 return LDAP_SUCCESS; 2361 } 2362 2363 static int 2364 IA5StringValidate( 2365 Syntax *syntax, 2366 struct berval *val ) 2367 { 2368 ber_len_t i; 2369 2370 for(i=0; i < val->bv_len; i++) { 2371 if( !LDAP_ASCII(val->bv_val[i]) ) { 2372 return LDAP_INVALID_SYNTAX; 2373 } 2374 } 2375 2376 return LDAP_SUCCESS; 2377 } 2378 2379 static int 2380 IA5StringNormalize( 2381 slap_mask_t use, 2382 Syntax *syntax, 2383 MatchingRule *mr, 2384 struct berval *val, 2385 struct berval *normalized, 2386 void *ctx ) 2387 { 2388 char *p, *q; 2389 int casefold = !SLAP_MR_ASSOCIATED( mr, 2390 slap_schema.si_mr_caseExactIA5Match ); 2391 2392 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 2393 2394 p = val->bv_val; 2395 2396 /* Ignore initial whitespace */ 2397 while ( ASCII_SPACE( *p ) ) p++; 2398 2399 normalized->bv_len = val->bv_len - ( p - val->bv_val ); 2400 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2401 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len ); 2402 normalized->bv_val[normalized->bv_len] = '\0'; 2403 2404 p = q = normalized->bv_val; 2405 2406 while ( *p ) { 2407 if ( ASCII_SPACE( *p ) ) { 2408 *q++ = *p++; 2409 2410 /* Ignore the extra whitespace */ 2411 while ( ASCII_SPACE( *p ) ) { 2412 p++; 2413 } 2414 2415 } else if ( casefold ) { 2416 /* Most IA5 rules require casefolding */ 2417 *q++ = TOLOWER(*p); p++; 2418 2419 } else { 2420 *q++ = *p++; 2421 } 2422 } 2423 2424 assert( normalized->bv_val <= p ); 2425 assert( q <= p ); 2426 2427 /* 2428 * If the string ended in space, backup the pointer one 2429 * position. One is enough because the above loop collapsed 2430 * all whitespace to a single space. 2431 */ 2432 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q; 2433 2434 /* null terminate */ 2435 *q = '\0'; 2436 2437 normalized->bv_len = q - normalized->bv_val; 2438 2439 return LDAP_SUCCESS; 2440 } 2441 2442 static int 2443 UUIDValidate( 2444 Syntax *syntax, 2445 struct berval *in ) 2446 { 2447 int i; 2448 if( in->bv_len != 36 ) { 2449 return LDAP_INVALID_SYNTAX; 2450 } 2451 2452 for( i=0; i<36; i++ ) { 2453 switch(i) { 2454 case 8: 2455 case 13: 2456 case 18: 2457 case 23: 2458 if( in->bv_val[i] != '-' ) { 2459 return LDAP_INVALID_SYNTAX; 2460 } 2461 break; 2462 default: 2463 if( !ASCII_HEX( in->bv_val[i]) ) { 2464 return LDAP_INVALID_SYNTAX; 2465 } 2466 } 2467 } 2468 2469 return LDAP_SUCCESS; 2470 } 2471 2472 static int 2473 UUIDPretty( 2474 Syntax *syntax, 2475 struct berval *in, 2476 struct berval *out, 2477 void *ctx ) 2478 { 2479 int i; 2480 int rc=LDAP_INVALID_SYNTAX; 2481 2482 assert( in != NULL ); 2483 assert( out != NULL ); 2484 2485 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX; 2486 2487 out->bv_len = 36; 2488 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 2489 2490 for( i=0; i<36; i++ ) { 2491 switch(i) { 2492 case 8: 2493 case 13: 2494 case 18: 2495 case 23: 2496 if( in->bv_val[i] != '-' ) { 2497 goto handle_error; 2498 } 2499 out->bv_val[i] = '-'; 2500 break; 2501 2502 default: 2503 if( !ASCII_HEX( in->bv_val[i]) ) { 2504 goto handle_error; 2505 } 2506 out->bv_val[i] = TOLOWER( in->bv_val[i] ); 2507 } 2508 } 2509 2510 rc = LDAP_SUCCESS; 2511 out->bv_val[ out->bv_len ] = '\0'; 2512 2513 if( 0 ) { 2514 handle_error: 2515 slap_sl_free( out->bv_val, ctx ); 2516 out->bv_val = NULL; 2517 } 2518 2519 return rc; 2520 } 2521 2522 int 2523 UUIDNormalize( 2524 slap_mask_t usage, 2525 Syntax *syntax, 2526 MatchingRule *mr, 2527 struct berval *val, 2528 struct berval *normalized, 2529 void *ctx ) 2530 { 2531 unsigned char octet = '\0'; 2532 int i; 2533 int j; 2534 2535 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) { 2536 /* NOTE: must be a normalized UUID */ 2537 assert( val->bv_len == 16 ); 2538 2539 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx ); 2540 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val, 2541 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE ); 2542 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) ); 2543 2544 return LDAP_SUCCESS; 2545 } 2546 2547 normalized->bv_len = 16; 2548 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2549 2550 for( i=0, j=0; i<36; i++ ) { 2551 unsigned char nibble; 2552 if( val->bv_val[i] == '-' ) { 2553 continue; 2554 2555 } else if( ASCII_DIGIT( val->bv_val[i] ) ) { 2556 nibble = val->bv_val[i] - '0'; 2557 2558 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) { 2559 nibble = val->bv_val[i] - ('a'-10); 2560 2561 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) { 2562 nibble = val->bv_val[i] - ('A'-10); 2563 2564 } else { 2565 slap_sl_free( normalized->bv_val, ctx ); 2566 return LDAP_INVALID_SYNTAX; 2567 } 2568 2569 if( j & 1 ) { 2570 octet |= nibble; 2571 normalized->bv_val[j>>1] = octet; 2572 } else { 2573 octet = nibble << 4; 2574 } 2575 j++; 2576 } 2577 2578 normalized->bv_val[normalized->bv_len] = 0; 2579 return LDAP_SUCCESS; 2580 } 2581 2582 2583 2584 int 2585 numericStringValidate( 2586 Syntax *syntax, 2587 struct berval *in ) 2588 { 2589 ber_len_t i; 2590 2591 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX; 2592 2593 for(i=0; i < in->bv_len; i++) { 2594 if( !SLAP_NUMERIC(in->bv_val[i]) ) { 2595 return LDAP_INVALID_SYNTAX; 2596 } 2597 } 2598 2599 return LDAP_SUCCESS; 2600 } 2601 2602 static int 2603 numericStringNormalize( 2604 slap_mask_t usage, 2605 Syntax *syntax, 2606 MatchingRule *mr, 2607 struct berval *val, 2608 struct berval *normalized, 2609 void *ctx ) 2610 { 2611 /* removal all spaces */ 2612 char *p, *q; 2613 2614 assert( !BER_BVISEMPTY( val ) ); 2615 2616 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 2617 2618 p = val->bv_val; 2619 q = normalized->bv_val; 2620 2621 while ( *p ) { 2622 if ( ASCII_SPACE( *p ) ) { 2623 /* Ignore whitespace */ 2624 p++; 2625 } else { 2626 *q++ = *p++; 2627 } 2628 } 2629 2630 /* we should have copied no more than is in val */ 2631 assert( (q - normalized->bv_val) <= (p - val->bv_val) ); 2632 2633 /* null terminate */ 2634 *q = '\0'; 2635 2636 normalized->bv_len = q - normalized->bv_val; 2637 2638 if( BER_BVISEMPTY( normalized ) ) { 2639 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx ); 2640 normalized->bv_val[0] = ' '; 2641 normalized->bv_val[1] = '\0'; 2642 normalized->bv_len = 1; 2643 } 2644 2645 return LDAP_SUCCESS; 2646 } 2647 2648 /* 2649 * Integer conversion macros that will use the largest available 2650 * type. 2651 */ 2652 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) 2653 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) 2654 # define SLAP_LONG long long 2655 #else 2656 # define SLAP_STRTOL(n,e,b) strtol(n,e,b) 2657 # define SLAP_LONG long 2658 #endif /* HAVE_STRTOLL ... */ 2659 2660 static int 2661 integerBitAndMatch( 2662 int *matchp, 2663 slap_mask_t flags, 2664 Syntax *syntax, 2665 MatchingRule *mr, 2666 struct berval *value, 2667 void *assertedValue ) 2668 { 2669 SLAP_LONG lValue, lAssertedValue; 2670 2671 errno = 0; 2672 /* safe to assume integers are NUL terminated? */ 2673 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 2674 if( errno == ERANGE ) 2675 { 2676 return LDAP_CONSTRAINT_VIOLATION; 2677 } 2678 2679 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, 2680 NULL, 10); 2681 if( errno == ERANGE ) 2682 { 2683 return LDAP_CONSTRAINT_VIOLATION; 2684 } 2685 2686 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1; 2687 return LDAP_SUCCESS; 2688 } 2689 2690 static int 2691 integerBitOrMatch( 2692 int *matchp, 2693 slap_mask_t flags, 2694 Syntax *syntax, 2695 MatchingRule *mr, 2696 struct berval *value, 2697 void *assertedValue ) 2698 { 2699 SLAP_LONG lValue, lAssertedValue; 2700 2701 errno = 0; 2702 /* safe to assume integers are NUL terminated? */ 2703 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 2704 if( errno == ERANGE ) 2705 { 2706 return LDAP_CONSTRAINT_VIOLATION; 2707 } 2708 2709 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, 2710 NULL, 10); 2711 if( errno == ERANGE ) 2712 { 2713 return LDAP_CONSTRAINT_VIOLATION; 2714 } 2715 2716 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1; 2717 return LDAP_SUCCESS; 2718 } 2719 2720 static int 2721 serialNumberAndIssuerCheck( 2722 struct berval *in, 2723 struct berval *sn, 2724 struct berval *is, 2725 void *ctx 2726 ) 2727 { 2728 int is_hex = 0, n; 2729 2730 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 2731 2732 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 2733 /* Parse old format */ 2734 is->bv_val = ber_bvchr( in, '$' ); 2735 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX; 2736 2737 sn->bv_val = in->bv_val; 2738 sn->bv_len = is->bv_val - in->bv_val; 2739 2740 is->bv_val++; 2741 is->bv_len = in->bv_len - (sn->bv_len + 1); 2742 2743 /* eat leading zeros */ 2744 for( n=0; n < (sn->bv_len-1); n++ ) { 2745 if( sn->bv_val[n] != '0' ) break; 2746 } 2747 sn->bv_val += n; 2748 sn->bv_len -= n; 2749 2750 for( n=0; n < sn->bv_len; n++ ) { 2751 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX; 2752 } 2753 2754 } else { 2755 /* Parse GSER format */ 2756 int havesn=0,haveissuer=0; 2757 struct berval x = *in; 2758 struct berval ni; 2759 x.bv_val++; 2760 x.bv_len-=2; 2761 2762 /* eat leading spaces */ 2763 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2764 /* empty */; 2765 } 2766 2767 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) { 2768 return LDAP_INVALID_SYNTAX; 2769 } 2770 2771 /* should be at issuer or serialNumber NamedValue */ 2772 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) { 2773 /* parse issuer */ 2774 x.bv_val += STRLENOF("issuer"); 2775 x.bv_len -= STRLENOF("issuer"); 2776 2777 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2778 x.bv_val++; x.bv_len--; 2779 2780 /* eat leading spaces */ 2781 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2782 /* empty */; 2783 } 2784 2785 /* For backward compatibility, this part is optional */ 2786 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { 2787 x.bv_val += STRLENOF("rdnSequence:"); 2788 x.bv_len -= STRLENOF("rdnSequence:"); 2789 } 2790 2791 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 2792 x.bv_val++; x.bv_len--; 2793 2794 is->bv_val = x.bv_val; 2795 is->bv_len = 0; 2796 2797 for( ; is->bv_len < x.bv_len; ) { 2798 if ( is->bv_val[is->bv_len] != '"' ) { 2799 is->bv_len++; 2800 continue; 2801 } 2802 if ( is->bv_val[is->bv_len+1] == '"' ) { 2803 /* double dquote */ 2804 is->bv_len+=2; 2805 continue; 2806 } 2807 break; 2808 } 2809 x.bv_val += is->bv_len+1; 2810 x.bv_len -= is->bv_len+1; 2811 2812 if ( x.bv_len < STRLENOF(",serialNumber 0")) { 2813 return LDAP_INVALID_SYNTAX; 2814 } 2815 2816 haveissuer++; 2817 2818 } else if( strncasecmp( x.bv_val, "serialNumber", 2819 STRLENOF("serialNumber")) == 0 ) 2820 { 2821 /* parse serialNumber */ 2822 int neg=0; 2823 x.bv_val += STRLENOF("serialNumber"); 2824 x.bv_len -= STRLENOF("serialNumber"); 2825 2826 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2827 x.bv_val++; x.bv_len--; 2828 2829 /* eat leading spaces */ 2830 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2831 /* empty */; 2832 } 2833 2834 sn->bv_val = x.bv_val; 2835 sn->bv_len = 0; 2836 2837 if( sn->bv_val[0] == '-' ) { 2838 neg++; 2839 sn->bv_len++; 2840 } 2841 2842 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || 2843 sn->bv_val[1] == 'X' )) { 2844 is_hex = 1; 2845 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2846 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2847 } 2848 } else if ( sn->bv_val[0] == '\'' ) { 2849 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2850 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2851 } 2852 if ( sn->bv_val[sn->bv_len] == '\'' && 2853 sn->bv_val[sn->bv_len+1] == 'H' ) 2854 is_hex = 1; 2855 else 2856 return LDAP_INVALID_SYNTAX; 2857 sn->bv_len += 2; 2858 } else { 2859 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2860 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; 2861 } 2862 } 2863 2864 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; 2865 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) { 2866 return LDAP_INVALID_SYNTAX; 2867 } 2868 2869 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len; 2870 2871 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) { 2872 return LDAP_INVALID_SYNTAX; 2873 } 2874 2875 havesn++; 2876 2877 } else return LDAP_INVALID_SYNTAX; 2878 2879 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX; 2880 x.bv_val++; x.bv_len--; 2881 2882 /* eat spaces */ 2883 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2884 /* empty */; 2885 } 2886 2887 /* should be at remaining NamedValue */ 2888 if( !haveissuer && (strncasecmp( x.bv_val, "issuer", 2889 STRLENOF("issuer" )) == 0 )) 2890 { 2891 /* parse issuer */ 2892 x.bv_val += STRLENOF("issuer"); 2893 x.bv_len -= STRLENOF("issuer"); 2894 2895 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2896 x.bv_val++; x.bv_len--; 2897 2898 /* eat leading spaces */ 2899 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2900 /* empty */; 2901 } 2902 2903 /* For backward compatibility, this part is optional */ 2904 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { 2905 x.bv_val += STRLENOF("rdnSequence:"); 2906 x.bv_len -= STRLENOF("rdnSequence:"); 2907 } 2908 2909 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 2910 x.bv_val++; x.bv_len--; 2911 2912 is->bv_val = x.bv_val; 2913 is->bv_len = 0; 2914 2915 for( ; is->bv_len < x.bv_len; ) { 2916 if ( is->bv_val[is->bv_len] != '"' ) { 2917 is->bv_len++; 2918 continue; 2919 } 2920 if ( is->bv_val[is->bv_len+1] == '"' ) { 2921 /* double dquote */ 2922 is->bv_len+=2; 2923 continue; 2924 } 2925 break; 2926 } 2927 x.bv_val += is->bv_len+1; 2928 x.bv_len -= is->bv_len+1; 2929 2930 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber", 2931 STRLENOF("serialNumber")) == 0 )) 2932 { 2933 /* parse serialNumber */ 2934 int neg=0; 2935 x.bv_val += STRLENOF("serialNumber"); 2936 x.bv_len -= STRLENOF("serialNumber"); 2937 2938 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2939 x.bv_val++; x.bv_len--; 2940 2941 /* eat leading spaces */ 2942 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) { 2943 /* empty */; 2944 } 2945 2946 sn->bv_val = x.bv_val; 2947 sn->bv_len = 0; 2948 2949 if( sn->bv_val[0] == '-' ) { 2950 neg++; 2951 sn->bv_len++; 2952 } 2953 2954 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || 2955 sn->bv_val[1] == 'X' )) { 2956 is_hex = 1; 2957 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2958 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2959 } 2960 } else if ( sn->bv_val[0] == '\'' ) { 2961 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2962 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2963 } 2964 if ( sn->bv_val[sn->bv_len] == '\'' && 2965 sn->bv_val[sn->bv_len+1] == 'H' ) 2966 is_hex = 1; 2967 else 2968 return LDAP_INVALID_SYNTAX; 2969 sn->bv_len += 2; 2970 } else { 2971 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2972 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; 2973 } 2974 } 2975 2976 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; 2977 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) { 2978 return LDAP_INVALID_SYNTAX; 2979 } 2980 2981 x.bv_val += sn->bv_len; 2982 x.bv_len -= sn->bv_len; 2983 2984 } else return LDAP_INVALID_SYNTAX; 2985 2986 /* eat trailing spaces */ 2987 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2988 /* empty */; 2989 } 2990 2991 /* should have no characters left... */ 2992 if( x.bv_len ) return LDAP_INVALID_SYNTAX; 2993 2994 ber_dupbv_x( &ni, is, ctx ); 2995 *is = ni; 2996 2997 /* need to handle double dquotes here */ 2998 } 2999 return 0; 3000 } 3001 3002 static int 3003 serialNumberAndIssuerValidate( 3004 Syntax *syntax, 3005 struct berval *in ) 3006 { 3007 int rc; 3008 struct berval sn, i; 3009 3010 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n", 3011 in->bv_val, 0, 0 ); 3012 3013 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL ); 3014 if ( rc ) 3015 return rc; 3016 3017 /* validate DN -- doesn't handle double dquote */ 3018 rc = dnValidate( NULL, &i ); 3019 if( rc ) 3020 rc = LDAP_INVALID_SYNTAX; 3021 3022 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3023 slap_sl_free( i.bv_val, NULL ); 3024 } 3025 3026 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n", 3027 0, 0, 0 ); 3028 return rc; 3029 } 3030 3031 int 3032 serialNumberAndIssuerPretty( 3033 Syntax *syntax, 3034 struct berval *in, 3035 struct berval *out, 3036 void *ctx ) 3037 { 3038 int n, rc; 3039 struct berval sn, i, ni; 3040 3041 assert( in != NULL ); 3042 assert( out != NULL ); 3043 3044 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", 3045 in->bv_val, 0, 0 ); 3046 3047 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3048 if ( rc ) 3049 return rc; 3050 3051 rc = dnPretty( syntax, &i, &ni, ctx ); 3052 3053 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3054 slap_sl_free( i.bv_val, ctx ); 3055 } 3056 3057 if( rc ) return LDAP_INVALID_SYNTAX; 3058 3059 /* make room from sn + "$" */ 3060 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }") 3061 + sn.bv_len + ni.bv_len; 3062 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3063 3064 if( out->bv_val == NULL ) { 3065 out->bv_len = 0; 3066 slap_sl_free( ni.bv_val, ctx ); 3067 return LDAP_OTHER; 3068 } 3069 3070 n = 0; 3071 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", 3072 STRLENOF("{ serialNumber ")); 3073 n = STRLENOF("{ serialNumber "); 3074 3075 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); 3076 n += sn.bv_len; 3077 3078 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\"")); 3079 n += STRLENOF(", issuer rdnSequence:\""); 3080 3081 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); 3082 n += ni.bv_len; 3083 3084 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }")); 3085 n += STRLENOF("\" }"); 3086 3087 out->bv_val[n] = '\0'; 3088 3089 assert( n == out->bv_len ); 3090 3091 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n", 3092 out->bv_val, 0, 0 ); 3093 3094 slap_sl_free( ni.bv_val, ctx ); 3095 3096 return LDAP_SUCCESS; 3097 } 3098 3099 /* 3100 * This routine is called by certificateExactNormalize when 3101 * certificateExactNormalize receives a search string instead of 3102 * a certificate. This routine checks if the search value is valid 3103 * and then returns the normalized value 3104 */ 3105 static int 3106 serialNumberAndIssuerNormalize( 3107 slap_mask_t usage, 3108 Syntax *syntax, 3109 MatchingRule *mr, 3110 struct berval *in, 3111 struct berval *out, 3112 void *ctx ) 3113 { 3114 struct berval sn, sn2, i, ni; 3115 char sbuf[64], *stmp = sbuf; 3116 int rc; 3117 ber_len_t n; 3118 3119 assert( in != NULL ); 3120 assert( out != NULL ); 3121 3122 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", 3123 in->bv_val, 0, 0 ); 3124 3125 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3126 if ( rc ) 3127 return rc; 3128 3129 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 3130 3131 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3132 slap_sl_free( i.bv_val, ctx ); 3133 } 3134 3135 if( rc ) return LDAP_INVALID_SYNTAX; 3136 3137 /* Convert sn to canonical hex */ 3138 if ( sn.bv_len > sizeof( sbuf )) { 3139 stmp = slap_sl_malloc( sn.bv_len, ctx ); 3140 } 3141 sn2.bv_val = stmp; 3142 sn2.bv_len = sn.bv_len; 3143 if ( lutil_str2bin( &sn, &sn2, ctx )) { 3144 rc = LDAP_INVALID_SYNTAX; 3145 goto func_leave; 3146 } 3147 3148 /* make room for sn + "$" */ 3149 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3150 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len; 3151 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3152 3153 if( out->bv_val == NULL ) { 3154 out->bv_len = 0; 3155 slap_sl_free( ni.bv_val, ctx ); 3156 rc = LDAP_OTHER; 3157 goto func_leave; 3158 } 3159 3160 n = 0; 3161 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", 3162 STRLENOF( "{ serialNumber " )); 3163 n = STRLENOF( "{ serialNumber " ); 3164 3165 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); 3166 { 3167 int j; 3168 unsigned char *v = (unsigned char *)sn2.bv_val; 3169 out->bv_val[n++] = '\''; 3170 for ( j = 0; j < sn2.bv_len; j++ ) { 3171 snprintf( &out->bv_val[n], out->bv_len - n + 1, 3172 "%02X", v[j] ); 3173 n += 2; 3174 } 3175 out->bv_val[n++] = '\''; 3176 out->bv_val[n++] = 'H'; 3177 } 3178 3179 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); 3180 n += STRLENOF( ", issuer rdnSequence:\"" ); 3181 3182 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); 3183 n += ni.bv_len; 3184 3185 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" )); 3186 n += STRLENOF( "\" }" ); 3187 3188 out->bv_val[n] = '\0'; 3189 3190 assert( n == out->bv_len ); 3191 3192 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n", 3193 out->bv_val, 0, 0 ); 3194 3195 func_leave: 3196 if ( stmp != sbuf ) 3197 slap_sl_free( stmp, ctx ); 3198 slap_sl_free( ni.bv_val, ctx ); 3199 3200 return rc; 3201 } 3202 3203 static int 3204 certificateExactNormalize( 3205 slap_mask_t usage, 3206 Syntax *syntax, 3207 MatchingRule *mr, 3208 struct berval *val, 3209 struct berval *normalized, 3210 void *ctx ) 3211 { 3212 BerElementBuffer berbuf; 3213 BerElement *ber = (BerElement *)&berbuf; 3214 ber_tag_t tag; 3215 ber_len_t len; 3216 ber_int_t i; 3217 char serialbuf[64], *serial = serialbuf; 3218 ber_len_t seriallen; 3219 struct berval issuer_dn = BER_BVNULL, bvdn; 3220 unsigned char *p; 3221 int rc = LDAP_INVALID_SYNTAX; 3222 3223 if( BER_BVISEMPTY( val ) ) goto done; 3224 3225 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3226 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx); 3227 } 3228 3229 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3230 3231 ber_init2( ber, val, LBER_USE_DER ); 3232 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 3233 tag = ber_skip_tag( ber, &len ); /* Sequence */ 3234 tag = ber_peek_tag( ber, &len ); /* Optional version? */ 3235 if ( tag == SLAP_X509_OPT_C_VERSION ) { 3236 tag = ber_skip_tag( ber, &len ); 3237 tag = ber_get_int( ber, &i ); /* version */ 3238 } 3239 3240 /* NOTE: move the test here from certificateValidate, 3241 * so that we can validate certs with serial longer 3242 * than sizeof(ber_int_t) */ 3243 tag = ber_peek_tag( ber, &len ); /* serial */ 3244 3245 /* Use hex format. '123456789abcdef'H 3246 */ 3247 { 3248 unsigned char *ptr; 3249 char *sptr; 3250 3251 tag = ber_skip_tag( ber, &len ); 3252 ptr = (unsigned char *)ber->ber_ptr; 3253 ber_skip_data( ber, len ); 3254 3255 /* Check for minimal encodings */ 3256 if ( len > 1 ) { 3257 if ( ptr[0] & 0x80 ) { 3258 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 )) 3259 return LDAP_INVALID_SYNTAX; 3260 } else if ( ptr[0] == 0 ) { 3261 if (!( ptr[1] & 0x80 )) 3262 return LDAP_INVALID_SYNTAX; 3263 } 3264 } 3265 3266 seriallen = len * 2 + 4; /* quotes, H, NUL */ 3267 if ( seriallen > sizeof( serialbuf )) 3268 serial = slap_sl_malloc( seriallen, ctx ); 3269 sptr = serial; 3270 *sptr++ = '\''; 3271 for ( i = 0; i<len; i++ ) { 3272 sprintf( sptr, "%02X", ptr[i] ); 3273 sptr += 2; 3274 } 3275 *sptr++ = '\''; 3276 *sptr++ = 'H'; 3277 seriallen--; 3278 } 3279 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */ 3280 ber_skip_data( ber, len ); 3281 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 3282 len = ber_ptrlen( ber ); 3283 bvdn.bv_val = val->bv_val + len; 3284 bvdn.bv_len = val->bv_len - len; 3285 3286 rc = dnX509normalize( &bvdn, &issuer_dn ); 3287 if( rc != LDAP_SUCCESS ) goto done; 3288 3289 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3290 + seriallen + issuer_dn.bv_len; 3291 normalized->bv_val = ch_malloc(normalized->bv_len+1); 3292 3293 p = (unsigned char *)normalized->bv_val; 3294 3295 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " )); 3296 p += STRLENOF( "{ serialNumber " ); 3297 3298 AC_MEMCPY(p, serial, seriallen); 3299 p += seriallen; 3300 3301 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); 3302 p += STRLENOF( ", issuer rdnSequence:\"" ); 3303 3304 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); 3305 p += issuer_dn.bv_len; 3306 3307 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" )); 3308 p += STRLENOF( "\" }" ); 3309 3310 *p = '\0'; 3311 3312 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n", 3313 normalized->bv_val, NULL, NULL ); 3314 3315 rc = LDAP_SUCCESS; 3316 3317 done: 3318 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 3319 if ( serial != serialbuf ) ber_memfree_x( serial, ctx ); 3320 3321 return rc; 3322 } 3323 3324 static int 3325 hexValidate( 3326 Syntax *syntax, 3327 struct berval *in ) 3328 { 3329 int i; 3330 3331 assert( in != NULL ); 3332 assert( !BER_BVISNULL( in ) ); 3333 3334 for ( i = 0; i < in->bv_len; i++ ) { 3335 if ( !ASCII_HEX( in->bv_val[ i ] ) ) { 3336 return LDAP_INVALID_SYNTAX; 3337 } 3338 } 3339 3340 return LDAP_SUCCESS; 3341 } 3342 3343 /* Normalize a SID as used inside a CSN: 3344 * three-digit numeric string */ 3345 static int 3346 hexNormalize( 3347 slap_mask_t usage, 3348 Syntax *syntax, 3349 MatchingRule *mr, 3350 struct berval *val, 3351 struct berval *normalized, 3352 void *ctx ) 3353 { 3354 int i; 3355 3356 assert( val != NULL ); 3357 assert( normalized != NULL ); 3358 3359 ber_dupbv_x( normalized, val, ctx ); 3360 3361 for ( i = 0; i < normalized->bv_len; i++ ) { 3362 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) { 3363 ber_memfree_x( normalized->bv_val, ctx ); 3364 BER_BVZERO( normalized ); 3365 return LDAP_INVALID_SYNTAX; 3366 } 3367 3368 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 3369 } 3370 3371 return LDAP_SUCCESS; 3372 } 3373 3374 static int 3375 sidValidate ( 3376 Syntax *syntax, 3377 struct berval *in ) 3378 { 3379 assert( in != NULL ); 3380 assert( !BER_BVISNULL( in ) ); 3381 3382 if ( in->bv_len != 3 ) { 3383 return LDAP_INVALID_SYNTAX; 3384 } 3385 3386 return hexValidate( NULL, in ); 3387 } 3388 3389 /* Normalize a SID as used inside a CSN: 3390 * three-digit numeric string */ 3391 static int 3392 sidNormalize( 3393 slap_mask_t usage, 3394 Syntax *syntax, 3395 MatchingRule *mr, 3396 struct berval *val, 3397 struct berval *normalized, 3398 void *ctx ) 3399 { 3400 if ( val->bv_len != 3 ) { 3401 return LDAP_INVALID_SYNTAX; 3402 } 3403 3404 return hexNormalize( 0, NULL, NULL, val, normalized, ctx ); 3405 } 3406 3407 static int 3408 sidPretty( 3409 Syntax *syntax, 3410 struct berval *val, 3411 struct berval *out, 3412 void *ctx ) 3413 { 3414 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 3415 } 3416 3417 /* Normalize a SID as used inside a CSN, either as-is 3418 * (assertion value) or extracted from the CSN 3419 * (attribute value) */ 3420 static int 3421 csnSidNormalize( 3422 slap_mask_t usage, 3423 Syntax *syntax, 3424 MatchingRule *mr, 3425 struct berval *val, 3426 struct berval *normalized, 3427 void *ctx ) 3428 { 3429 struct berval bv; 3430 char *ptr, 3431 buf[ 4 ]; 3432 3433 3434 if ( BER_BVISEMPTY( val ) ) { 3435 return LDAP_INVALID_SYNTAX; 3436 } 3437 3438 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3439 return sidNormalize( 0, NULL, NULL, val, normalized, ctx ); 3440 } 3441 3442 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3443 3444 ptr = ber_bvchr( val, '#' ); 3445 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3446 return LDAP_INVALID_SYNTAX; 3447 } 3448 3449 bv.bv_val = ptr + 1; 3450 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 3451 3452 ptr = ber_bvchr( &bv, '#' ); 3453 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3454 return LDAP_INVALID_SYNTAX; 3455 } 3456 3457 bv.bv_val = ptr + 1; 3458 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 3459 3460 ptr = ber_bvchr( &bv, '#' ); 3461 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3462 return LDAP_INVALID_SYNTAX; 3463 } 3464 3465 bv.bv_len = ptr - bv.bv_val; 3466 3467 if ( bv.bv_len == 2 ) { 3468 /* OpenLDAP 2.3 SID */ 3469 buf[ 0 ] = '0'; 3470 buf[ 1 ] = bv.bv_val[ 0 ]; 3471 buf[ 2 ] = bv.bv_val[ 1 ]; 3472 buf[ 3 ] = '\0'; 3473 3474 bv.bv_val = buf; 3475 bv.bv_len = 3; 3476 } 3477 3478 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx ); 3479 } 3480 3481 static int 3482 csnValidate( 3483 Syntax *syntax, 3484 struct berval *in ) 3485 { 3486 struct berval bv; 3487 char *ptr; 3488 int rc; 3489 3490 assert( in != NULL ); 3491 assert( !BER_BVISNULL( in ) ); 3492 3493 if ( BER_BVISEMPTY( in ) ) { 3494 return LDAP_INVALID_SYNTAX; 3495 } 3496 3497 bv = *in; 3498 3499 ptr = ber_bvchr( &bv, '#' ); 3500 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) { 3501 return LDAP_INVALID_SYNTAX; 3502 } 3503 3504 bv.bv_len = ptr - bv.bv_val; 3505 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) && 3506 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) 3507 { 3508 return LDAP_INVALID_SYNTAX; 3509 } 3510 3511 rc = generalizedTimeValidate( NULL, &bv ); 3512 if ( rc != LDAP_SUCCESS ) { 3513 return rc; 3514 } 3515 3516 bv.bv_val = ptr + 1; 3517 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3518 3519 ptr = ber_bvchr( &bv, '#' ); 3520 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { 3521 return LDAP_INVALID_SYNTAX; 3522 } 3523 3524 bv.bv_len = ptr - bv.bv_val; 3525 if ( bv.bv_len != 6 ) { 3526 return LDAP_INVALID_SYNTAX; 3527 } 3528 3529 rc = hexValidate( NULL, &bv ); 3530 if ( rc != LDAP_SUCCESS ) { 3531 return rc; 3532 } 3533 3534 bv.bv_val = ptr + 1; 3535 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3536 3537 ptr = ber_bvchr( &bv, '#' ); 3538 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { 3539 return LDAP_INVALID_SYNTAX; 3540 } 3541 3542 bv.bv_len = ptr - bv.bv_val; 3543 if ( bv.bv_len == 2 ) { 3544 /* tolerate old 2-digit replica-id */ 3545 rc = hexValidate( NULL, &bv ); 3546 3547 } else { 3548 rc = sidValidate( NULL, &bv ); 3549 } 3550 if ( rc != LDAP_SUCCESS ) { 3551 return rc; 3552 } 3553 3554 bv.bv_val = ptr + 1; 3555 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3556 3557 if ( bv.bv_len != 6 ) { 3558 return LDAP_INVALID_SYNTAX; 3559 } 3560 3561 return hexValidate( NULL, &bv ); 3562 } 3563 3564 /* Normalize a CSN in OpenLDAP 2.1 format */ 3565 static int 3566 csnNormalize21( 3567 slap_mask_t usage, 3568 Syntax *syntax, 3569 MatchingRule *mr, 3570 struct berval *val, 3571 struct berval *normalized, 3572 void *ctx ) 3573 { 3574 struct berval gt, cnt, sid, mod; 3575 struct berval bv; 3576 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 3577 char *ptr; 3578 int i; 3579 3580 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3581 assert( !BER_BVISEMPTY( val ) ); 3582 3583 gt = *val; 3584 3585 ptr = ber_bvchr( >, '#' ); 3586 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) { 3587 return LDAP_INVALID_SYNTAX; 3588 } 3589 3590 gt.bv_len = ptr - gt.bv_val; 3591 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) { 3592 return LDAP_INVALID_SYNTAX; 3593 } 3594 3595 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) { 3596 return LDAP_INVALID_SYNTAX; 3597 } 3598 3599 cnt.bv_val = ptr + 1; 3600 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3601 3602 ptr = ber_bvchr( &cnt, '#' ); 3603 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3604 return LDAP_INVALID_SYNTAX; 3605 } 3606 3607 cnt.bv_len = ptr - cnt.bv_val; 3608 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) { 3609 return LDAP_INVALID_SYNTAX; 3610 } 3611 3612 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) { 3613 return LDAP_INVALID_SYNTAX; 3614 } 3615 3616 cnt.bv_val += STRLENOF( "0x" ); 3617 cnt.bv_len -= STRLENOF( "0x" ); 3618 3619 sid.bv_val = ptr + 1; 3620 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3621 3622 ptr = ber_bvchr( &sid, '#' ); 3623 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3624 return LDAP_INVALID_SYNTAX; 3625 } 3626 3627 sid.bv_len = ptr - sid.bv_val; 3628 if ( sid.bv_len != STRLENOF( "0" ) ) { 3629 return LDAP_INVALID_SYNTAX; 3630 } 3631 3632 mod.bv_val = ptr + 1; 3633 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3634 if ( mod.bv_len != STRLENOF( "0000" ) ) { 3635 return LDAP_INVALID_SYNTAX; 3636 } 3637 3638 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 3639 bv.bv_val = buf; 3640 3641 ptr = bv.bv_val; 3642 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) ); 3643 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ], 3644 STRLENOF( "MM" ) ); 3645 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ], 3646 STRLENOF( "SS" ) ); 3647 ptr = lutil_strcopy( ptr, ".000000Z#00" ); 3648 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len ); 3649 *ptr++ = '#'; 3650 *ptr++ = '0'; 3651 *ptr++ = '0'; 3652 *ptr++ = sid.bv_val[ 0 ]; 3653 *ptr++ = '#'; 3654 *ptr++ = '0'; 3655 *ptr++ = '0'; 3656 for ( i = 0; i < mod.bv_len; i++ ) { 3657 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 3658 } 3659 *ptr = '\0'; 3660 3661 assert( ptr - bv.bv_val == bv.bv_len ); 3662 3663 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 3664 return LDAP_INVALID_SYNTAX; 3665 } 3666 3667 ber_dupbv_x( normalized, &bv, ctx ); 3668 3669 return LDAP_SUCCESS; 3670 } 3671 3672 /* Normalize a CSN in OpenLDAP 2.3 format */ 3673 static int 3674 csnNormalize23( 3675 slap_mask_t usage, 3676 Syntax *syntax, 3677 MatchingRule *mr, 3678 struct berval *val, 3679 struct berval *normalized, 3680 void *ctx ) 3681 { 3682 struct berval gt, cnt, sid, mod; 3683 struct berval bv; 3684 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 3685 char *ptr; 3686 int i; 3687 3688 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3689 assert( !BER_BVISEMPTY( val ) ); 3690 3691 gt = *val; 3692 3693 ptr = ber_bvchr( >, '#' ); 3694 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) { 3695 return LDAP_INVALID_SYNTAX; 3696 } 3697 3698 gt.bv_len = ptr - gt.bv_val; 3699 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 3700 return LDAP_INVALID_SYNTAX; 3701 } 3702 3703 cnt.bv_val = ptr + 1; 3704 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3705 3706 ptr = ber_bvchr( &cnt, '#' ); 3707 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3708 return LDAP_INVALID_SYNTAX; 3709 } 3710 3711 cnt.bv_len = ptr - cnt.bv_val; 3712 if ( cnt.bv_len != STRLENOF( "000000" ) ) { 3713 return LDAP_INVALID_SYNTAX; 3714 } 3715 3716 sid.bv_val = ptr + 1; 3717 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3718 3719 ptr = ber_bvchr( &sid, '#' ); 3720 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3721 return LDAP_INVALID_SYNTAX; 3722 } 3723 3724 sid.bv_len = ptr - sid.bv_val; 3725 if ( sid.bv_len != STRLENOF( "00" ) ) { 3726 return LDAP_INVALID_SYNTAX; 3727 } 3728 3729 mod.bv_val = ptr + 1; 3730 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3731 if ( mod.bv_len != STRLENOF( "000000" ) ) { 3732 return LDAP_INVALID_SYNTAX; 3733 } 3734 3735 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 3736 bv.bv_val = buf; 3737 3738 ptr = bv.bv_val; 3739 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 ); 3740 ptr = lutil_strcopy( ptr, ".000000Z#" ); 3741 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len ); 3742 *ptr++ = '#'; 3743 *ptr++ = '0'; 3744 for ( i = 0; i < sid.bv_len; i++ ) { 3745 *ptr++ = TOLOWER( sid.bv_val[ i ] ); 3746 } 3747 *ptr++ = '#'; 3748 for ( i = 0; i < mod.bv_len; i++ ) { 3749 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 3750 } 3751 *ptr = '\0'; 3752 3753 assert( ptr - bv.bv_val == bv.bv_len ); 3754 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 3755 return LDAP_INVALID_SYNTAX; 3756 } 3757 3758 ber_dupbv_x( normalized, &bv, ctx ); 3759 3760 return LDAP_SUCCESS; 3761 } 3762 3763 /* Normalize a CSN */ 3764 static int 3765 csnNormalize( 3766 slap_mask_t usage, 3767 Syntax *syntax, 3768 MatchingRule *mr, 3769 struct berval *val, 3770 struct berval *normalized, 3771 void *ctx ) 3772 { 3773 struct berval cnt, sid, mod; 3774 char *ptr; 3775 int i; 3776 3777 assert( val != NULL ); 3778 assert( normalized != NULL ); 3779 3780 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3781 3782 if ( BER_BVISEMPTY( val ) ) { 3783 return LDAP_INVALID_SYNTAX; 3784 } 3785 3786 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) { 3787 /* Openldap <= 2.3 */ 3788 3789 return csnNormalize23( usage, syntax, mr, val, normalized, ctx ); 3790 } 3791 3792 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) { 3793 /* Openldap 2.1 */ 3794 3795 return csnNormalize21( usage, syntax, mr, val, normalized, ctx ); 3796 } 3797 3798 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) { 3799 return LDAP_INVALID_SYNTAX; 3800 } 3801 3802 ptr = ber_bvchr( val, '#' ); 3803 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3804 return LDAP_INVALID_SYNTAX; 3805 } 3806 3807 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) { 3808 return LDAP_INVALID_SYNTAX; 3809 } 3810 3811 cnt.bv_val = ptr + 1; 3812 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3813 3814 ptr = ber_bvchr( &cnt, '#' ); 3815 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3816 return LDAP_INVALID_SYNTAX; 3817 } 3818 3819 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) { 3820 return LDAP_INVALID_SYNTAX; 3821 } 3822 3823 sid.bv_val = ptr + 1; 3824 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3825 3826 ptr = ber_bvchr( &sid, '#' ); 3827 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3828 return LDAP_INVALID_SYNTAX; 3829 } 3830 3831 sid.bv_len = ptr - sid.bv_val; 3832 if ( sid.bv_len != STRLENOF( "000" ) ) { 3833 return LDAP_INVALID_SYNTAX; 3834 } 3835 3836 mod.bv_val = ptr + 1; 3837 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3838 3839 if ( mod.bv_len != STRLENOF( "000000" ) ) { 3840 return LDAP_INVALID_SYNTAX; 3841 } 3842 3843 ber_dupbv_x( normalized, val, ctx ); 3844 3845 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" ); 3846 i < normalized->bv_len; i++ ) 3847 { 3848 /* assume it's already validated that's all hex digits */ 3849 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 3850 } 3851 3852 return LDAP_SUCCESS; 3853 } 3854 3855 static int 3856 csnPretty( 3857 Syntax *syntax, 3858 struct berval *val, 3859 struct berval *out, 3860 void *ctx ) 3861 { 3862 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 3863 } 3864 3865 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX 3866 /* slight optimization - does not need the start parameter */ 3867 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f) 3868 enum { start = 0 }; 3869 #endif 3870 3871 static int 3872 check_time_syntax (struct berval *val, 3873 int start, 3874 int *parts, 3875 struct berval *fraction) 3876 { 3877 /* 3878 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) 3879 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM] 3880 * GeneralizedTime supports leap seconds, UTCTime does not. 3881 */ 3882 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 }; 3883 static const int mdays[2][12] = { 3884 /* non-leap years */ 3885 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 3886 /* leap years */ 3887 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 3888 }; 3889 char *p, *e; 3890 int part, c, c1, c2, tzoffset, leapyear = 0; 3891 3892 p = val->bv_val; 3893 e = p + val->bv_len; 3894 3895 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 3896 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */ 3897 #endif 3898 for (part = start; part < 7 && p < e; part++) { 3899 c1 = *p; 3900 if (!ASCII_DIGIT(c1)) { 3901 break; 3902 } 3903 p++; 3904 if (p == e) { 3905 return LDAP_INVALID_SYNTAX; 3906 } 3907 c = *p++; 3908 if (!ASCII_DIGIT(c)) { 3909 return LDAP_INVALID_SYNTAX; 3910 } 3911 c += c1 * 10 - '0' * 11; 3912 if ((part | 1) == 3) { 3913 --c; 3914 if (c < 0) { 3915 return LDAP_INVALID_SYNTAX; 3916 } 3917 } 3918 if (c >= ceiling[part]) { 3919 if (! (c == 60 && part == 6 && start == 0)) 3920 return LDAP_INVALID_SYNTAX; 3921 } 3922 parts[part] = c; 3923 } 3924 if (part < 5 + start) { 3925 return LDAP_INVALID_SYNTAX; 3926 } 3927 for (; part < 9; part++) { 3928 parts[part] = 0; 3929 } 3930 3931 /* leapyear check for the Gregorian calendar (year>1581) */ 3932 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) { 3933 leapyear = 1; 3934 } 3935 3936 if (parts[3] >= mdays[leapyear][parts[2]]) { 3937 return LDAP_INVALID_SYNTAX; 3938 } 3939 3940 if (start == 0) { 3941 fraction->bv_val = p; 3942 fraction->bv_len = 0; 3943 if (p < e && (*p == '.' || *p == ',')) { 3944 char *end_num; 3945 while (++p < e && ASCII_DIGIT(*p)) { 3946 /* EMTPY */; 3947 } 3948 if (p - fraction->bv_val == 1) { 3949 return LDAP_INVALID_SYNTAX; 3950 } 3951 for (end_num = p; end_num[-1] == '0'; --end_num) { 3952 /* EMPTY */; 3953 } 3954 c = end_num - fraction->bv_val; 3955 if (c != 1) fraction->bv_len = c; 3956 } 3957 } 3958 3959 if (p == e) { 3960 /* no time zone */ 3961 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 3962 } 3963 3964 tzoffset = *p++; 3965 switch (tzoffset) { 3966 default: 3967 return LDAP_INVALID_SYNTAX; 3968 case 'Z': 3969 /* UTC */ 3970 break; 3971 case '+': 3972 case '-': 3973 for (part = 7; part < 9 && p < e; part++) { 3974 c1 = *p; 3975 if (!ASCII_DIGIT(c1)) { 3976 break; 3977 } 3978 p++; 3979 if (p == e) { 3980 return LDAP_INVALID_SYNTAX; 3981 } 3982 c2 = *p++; 3983 if (!ASCII_DIGIT(c2)) { 3984 return LDAP_INVALID_SYNTAX; 3985 } 3986 parts[part] = c1 * 10 + c2 - '0' * 11; 3987 if (parts[part] >= ceiling[part]) { 3988 return LDAP_INVALID_SYNTAX; 3989 } 3990 } 3991 if (part < 8 + start) { 3992 return LDAP_INVALID_SYNTAX; 3993 } 3994 3995 if (tzoffset == '-') { 3996 /* negative offset to UTC, ie west of Greenwich */ 3997 parts[4] += parts[7]; 3998 parts[5] += parts[8]; 3999 /* offset is just hhmm, no seconds */ 4000 for (part = 6; --part >= 0; ) { 4001 if (part != 3) { 4002 c = ceiling[part]; 4003 } else { 4004 c = mdays[leapyear][parts[2]]; 4005 } 4006 if (parts[part] >= c) { 4007 if (part == 0) { 4008 return LDAP_INVALID_SYNTAX; 4009 } 4010 parts[part] -= c; 4011 parts[part - 1]++; 4012 continue; 4013 } else if (part != 5) { 4014 break; 4015 } 4016 } 4017 } else { 4018 /* positive offset to UTC, ie east of Greenwich */ 4019 parts[4] -= parts[7]; 4020 parts[5] -= parts[8]; 4021 for (part = 6; --part >= 0; ) { 4022 if (parts[part] < 0) { 4023 if (part == 0) { 4024 return LDAP_INVALID_SYNTAX; 4025 } 4026 if (part != 3) { 4027 c = ceiling[part]; 4028 } else { 4029 /* make first arg to % non-negative */ 4030 c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; 4031 } 4032 parts[part] += c; 4033 parts[part - 1]--; 4034 continue; 4035 } else if (part != 5) { 4036 break; 4037 } 4038 } 4039 } 4040 } 4041 4042 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 4043 } 4044 4045 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 4046 4047 #if 0 4048 static int 4049 xutcTimeNormalize( 4050 Syntax *syntax, 4051 struct berval *val, 4052 struct berval *normalized ) 4053 { 4054 int parts[9], rc; 4055 4056 rc = check_time_syntax(val, 1, parts, NULL); 4057 if (rc != LDAP_SUCCESS) { 4058 return rc; 4059 } 4060 4061 normalized->bv_val = ch_malloc( 14 ); 4062 if ( normalized->bv_val == NULL ) { 4063 return LBER_ERROR_MEMORY; 4064 } 4065 4066 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ", 4067 parts[1], parts[2] + 1, parts[3] + 1, 4068 parts[4], parts[5], parts[6] ); 4069 normalized->bv_len = 13; 4070 4071 return LDAP_SUCCESS; 4072 } 4073 #endif /* 0 */ 4074 4075 static int 4076 utcTimeValidate( 4077 Syntax *syntax, 4078 struct berval *in ) 4079 { 4080 int parts[9]; 4081 return check_time_syntax(in, 1, parts, NULL); 4082 } 4083 4084 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ 4085 4086 static int 4087 generalizedTimeValidate( 4088 Syntax *syntax, 4089 struct berval *in ) 4090 { 4091 int parts[9]; 4092 struct berval fraction; 4093 return check_time_syntax(in, 0, parts, &fraction); 4094 } 4095 4096 static int 4097 generalizedTimeNormalize( 4098 slap_mask_t usage, 4099 Syntax *syntax, 4100 MatchingRule *mr, 4101 struct berval *val, 4102 struct berval *normalized, 4103 void *ctx ) 4104 { 4105 int parts[9], rc; 4106 unsigned int len; 4107 struct berval fraction; 4108 4109 rc = check_time_syntax(val, 0, parts, &fraction); 4110 if (rc != LDAP_SUCCESS) { 4111 return rc; 4112 } 4113 4114 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len; 4115 normalized->bv_val = slap_sl_malloc( len + 1, ctx ); 4116 if ( BER_BVISNULL( normalized ) ) { 4117 return LBER_ERROR_MEMORY; 4118 } 4119 4120 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d", 4121 parts[0], parts[1], parts[2] + 1, parts[3] + 1, 4122 parts[4], parts[5], parts[6] ); 4123 if ( !BER_BVISEMPTY( &fraction ) ) { 4124 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1, 4125 fraction.bv_val, fraction.bv_len ); 4126 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.'; 4127 } 4128 strcpy( normalized->bv_val + len-1, "Z" ); 4129 normalized->bv_len = len; 4130 4131 return LDAP_SUCCESS; 4132 } 4133 4134 static int 4135 generalizedTimeOrderingMatch( 4136 int *matchp, 4137 slap_mask_t flags, 4138 Syntax *syntax, 4139 MatchingRule *mr, 4140 struct berval *value, 4141 void *assertedValue ) 4142 { 4143 struct berval *asserted = (struct berval *) assertedValue; 4144 ber_len_t v_len = value->bv_len; 4145 ber_len_t av_len = asserted->bv_len; 4146 4147 /* ignore trailing 'Z' when comparing */ 4148 int match = memcmp( value->bv_val, asserted->bv_val, 4149 (v_len < av_len ? v_len : av_len) - 1 ); 4150 if ( match == 0 ) match = v_len - av_len; 4151 4152 *matchp = match; 4153 return LDAP_SUCCESS; 4154 } 4155 4156 /* Index generation function */ 4157 int generalizedTimeIndexer( 4158 slap_mask_t use, 4159 slap_mask_t flags, 4160 Syntax *syntax, 4161 MatchingRule *mr, 4162 struct berval *prefix, 4163 BerVarray values, 4164 BerVarray *keysp, 4165 void *ctx ) 4166 { 4167 int i, j; 4168 BerVarray keys; 4169 char tmp[5]; 4170 BerValue bvtmp; /* 40 bit index */ 4171 struct lutil_tm tm; 4172 struct lutil_timet tt; 4173 4174 bvtmp.bv_len = sizeof(tmp); 4175 bvtmp.bv_val = tmp; 4176 for( i=0; values[i].bv_val != NULL; i++ ) { 4177 /* just count them */ 4178 } 4179 4180 /* we should have at least one value at this point */ 4181 assert( i > 0 ); 4182 4183 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 4184 4185 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 4186 for( i=0, j=0; values[i].bv_val != NULL; i++ ) { 4187 assert(values[i].bv_val != NULL && values[i].bv_len >= 10); 4188 /* Use 40 bits of time for key */ 4189 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) { 4190 lutil_tm2time( &tm, &tt ); 4191 tmp[0] = tt.tt_gsec & 0xff; 4192 tmp[4] = tt.tt_sec & 0xff; 4193 tt.tt_sec >>= 8; 4194 tmp[3] = tt.tt_sec & 0xff; 4195 tt.tt_sec >>= 8; 4196 tmp[2] = tt.tt_sec & 0xff; 4197 tt.tt_sec >>= 8; 4198 tmp[1] = tt.tt_sec & 0xff; 4199 4200 ber_dupbv_x(&keys[j++], &bvtmp, ctx ); 4201 } 4202 } 4203 4204 keys[j].bv_val = NULL; 4205 keys[j].bv_len = 0; 4206 4207 *keysp = keys; 4208 4209 return LDAP_SUCCESS; 4210 } 4211 4212 /* Index generation function */ 4213 int generalizedTimeFilter( 4214 slap_mask_t use, 4215 slap_mask_t flags, 4216 Syntax *syntax, 4217 MatchingRule *mr, 4218 struct berval *prefix, 4219 void * assertedValue, 4220 BerVarray *keysp, 4221 void *ctx ) 4222 { 4223 BerVarray keys; 4224 char tmp[5]; 4225 BerValue bvtmp; /* 40 bit index */ 4226 BerValue *value = (BerValue *) assertedValue; 4227 struct lutil_tm tm; 4228 struct lutil_timet tt; 4229 4230 bvtmp.bv_len = sizeof(tmp); 4231 bvtmp.bv_val = tmp; 4232 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 4233 /* Use 40 bits of time for key */ 4234 if ( value->bv_val && value->bv_len >= 10 && 4235 lutil_parsetime( value->bv_val, &tm ) == 0 ) { 4236 4237 lutil_tm2time( &tm, &tt ); 4238 tmp[0] = tt.tt_gsec & 0xff; 4239 tmp[4] = tt.tt_sec & 0xff; 4240 tt.tt_sec >>= 8; 4241 tmp[3] = tt.tt_sec & 0xff; 4242 tt.tt_sec >>= 8; 4243 tmp[2] = tt.tt_sec & 0xff; 4244 tt.tt_sec >>= 8; 4245 tmp[1] = tt.tt_sec & 0xff; 4246 4247 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 4248 ber_dupbv_x(keys, &bvtmp, ctx ); 4249 keys[1].bv_val = NULL; 4250 keys[1].bv_len = 0; 4251 } else { 4252 keys = NULL; 4253 } 4254 4255 *keysp = keys; 4256 4257 return LDAP_SUCCESS; 4258 } 4259 4260 static int 4261 deliveryMethodValidate( 4262 Syntax *syntax, 4263 struct berval *val ) 4264 { 4265 #undef LENOF 4266 #define LENOF(s) (sizeof(s)-1) 4267 struct berval tmp = *val; 4268 /* 4269 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod ) 4270 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" / 4271 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone" 4272 */ 4273 again: 4274 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4275 4276 switch( tmp.bv_val[0] ) { 4277 case 'a': 4278 case 'A': 4279 if(( tmp.bv_len >= LENOF("any") ) && 4280 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 )) 4281 { 4282 tmp.bv_len -= LENOF("any"); 4283 tmp.bv_val += LENOF("any"); 4284 break; 4285 } 4286 return LDAP_INVALID_SYNTAX; 4287 4288 case 'm': 4289 case 'M': 4290 if(( tmp.bv_len >= LENOF("mhs") ) && 4291 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 )) 4292 { 4293 tmp.bv_len -= LENOF("mhs"); 4294 tmp.bv_val += LENOF("mhs"); 4295 break; 4296 } 4297 return LDAP_INVALID_SYNTAX; 4298 4299 case 'p': 4300 case 'P': 4301 if(( tmp.bv_len >= LENOF("physical") ) && 4302 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 )) 4303 { 4304 tmp.bv_len -= LENOF("physical"); 4305 tmp.bv_val += LENOF("physical"); 4306 break; 4307 } 4308 return LDAP_INVALID_SYNTAX; 4309 4310 case 't': 4311 case 'T': /* telex or teletex or telephone */ 4312 if(( tmp.bv_len >= LENOF("telex") ) && 4313 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 )) 4314 { 4315 tmp.bv_len -= LENOF("telex"); 4316 tmp.bv_val += LENOF("telex"); 4317 break; 4318 } 4319 if(( tmp.bv_len >= LENOF("teletex") ) && 4320 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 )) 4321 { 4322 tmp.bv_len -= LENOF("teletex"); 4323 tmp.bv_val += LENOF("teletex"); 4324 break; 4325 } 4326 if(( tmp.bv_len >= LENOF("telephone") ) && 4327 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 )) 4328 { 4329 tmp.bv_len -= LENOF("telephone"); 4330 tmp.bv_val += LENOF("telephone"); 4331 break; 4332 } 4333 return LDAP_INVALID_SYNTAX; 4334 4335 case 'g': 4336 case 'G': /* g3fax or g4fax */ 4337 if(( tmp.bv_len >= LENOF("g3fax") ) && ( 4338 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) || 4339 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 ))) 4340 { 4341 tmp.bv_len -= LENOF("g3fax"); 4342 tmp.bv_val += LENOF("g3fax"); 4343 break; 4344 } 4345 return LDAP_INVALID_SYNTAX; 4346 4347 case 'i': 4348 case 'I': 4349 if(( tmp.bv_len >= LENOF("ia5") ) && 4350 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 )) 4351 { 4352 tmp.bv_len -= LENOF("ia5"); 4353 tmp.bv_val += LENOF("ia5"); 4354 break; 4355 } 4356 return LDAP_INVALID_SYNTAX; 4357 4358 case 'v': 4359 case 'V': 4360 if(( tmp.bv_len >= LENOF("videotex") ) && 4361 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 )) 4362 { 4363 tmp.bv_len -= LENOF("videotex"); 4364 tmp.bv_val += LENOF("videotex"); 4365 break; 4366 } 4367 return LDAP_INVALID_SYNTAX; 4368 4369 default: 4370 return LDAP_INVALID_SYNTAX; 4371 } 4372 4373 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS; 4374 4375 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 4376 tmp.bv_len++; 4377 tmp.bv_val--; 4378 } 4379 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) { 4380 tmp.bv_len++; 4381 tmp.bv_val--; 4382 } else { 4383 return LDAP_INVALID_SYNTAX; 4384 } 4385 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 4386 tmp.bv_len++; 4387 tmp.bv_val--; 4388 } 4389 4390 goto again; 4391 } 4392 4393 static int 4394 nisNetgroupTripleValidate( 4395 Syntax *syntax, 4396 struct berval *val ) 4397 { 4398 char *p, *e; 4399 int commas = 0; 4400 4401 if ( BER_BVISEMPTY( val ) ) { 4402 return LDAP_INVALID_SYNTAX; 4403 } 4404 4405 p = (char *)val->bv_val; 4406 e = p + val->bv_len; 4407 4408 if ( *p != '(' /*')'*/ ) { 4409 return LDAP_INVALID_SYNTAX; 4410 } 4411 4412 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) { 4413 if ( *p == ',' ) { 4414 commas++; 4415 if ( commas > 2 ) { 4416 return LDAP_INVALID_SYNTAX; 4417 } 4418 4419 } else if ( !AD_CHAR( *p ) ) { 4420 return LDAP_INVALID_SYNTAX; 4421 } 4422 } 4423 4424 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) { 4425 return LDAP_INVALID_SYNTAX; 4426 } 4427 4428 p++; 4429 4430 if (p != e) { 4431 return LDAP_INVALID_SYNTAX; 4432 } 4433 4434 return LDAP_SUCCESS; 4435 } 4436 4437 static int 4438 bootParameterValidate( 4439 Syntax *syntax, 4440 struct berval *val ) 4441 { 4442 char *p, *e; 4443 4444 if ( BER_BVISEMPTY( val ) ) { 4445 return LDAP_INVALID_SYNTAX; 4446 } 4447 4448 p = (char *)val->bv_val; 4449 e = p + val->bv_len; 4450 4451 /* key */ 4452 for (; ( p < e ) && ( *p != '=' ); p++ ) { 4453 if ( !AD_CHAR( *p ) ) { 4454 return LDAP_INVALID_SYNTAX; 4455 } 4456 } 4457 4458 if ( *p != '=' ) { 4459 return LDAP_INVALID_SYNTAX; 4460 } 4461 4462 /* server */ 4463 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) { 4464 if ( !AD_CHAR( *p ) ) { 4465 return LDAP_INVALID_SYNTAX; 4466 } 4467 } 4468 4469 if ( *p != ':' ) { 4470 return LDAP_INVALID_SYNTAX; 4471 } 4472 4473 /* path */ 4474 for ( p++; p < e; p++ ) { 4475 if ( !SLAP_PRINTABLE( *p ) ) { 4476 return LDAP_INVALID_SYNTAX; 4477 } 4478 } 4479 4480 return LDAP_SUCCESS; 4481 } 4482 4483 static int 4484 firstComponentNormalize( 4485 slap_mask_t usage, 4486 Syntax *syntax, 4487 MatchingRule *mr, 4488 struct berval *val, 4489 struct berval *normalized, 4490 void *ctx ) 4491 { 4492 int rc; 4493 struct berval comp; 4494 ber_len_t len; 4495 4496 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) { 4497 ber_dupbv_x( normalized, val, ctx ); 4498 return LDAP_SUCCESS; 4499 } 4500 4501 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4502 4503 if( val->bv_val[0] != '(' /*')'*/ && 4504 val->bv_val[0] != '{' /*'}'*/ ) 4505 { 4506 return LDAP_INVALID_SYNTAX; 4507 } 4508 4509 /* trim leading white space */ 4510 for( len=1; 4511 len < val->bv_len && ASCII_SPACE(val->bv_val[len]); 4512 len++ ) 4513 { 4514 /* empty */ 4515 } 4516 4517 /* grab next word */ 4518 comp.bv_val = &val->bv_val[len]; 4519 len = val->bv_len - len; 4520 for( comp.bv_len = 0; 4521 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len; 4522 comp.bv_len++ ) 4523 { 4524 /* empty */ 4525 } 4526 4527 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) { 4528 rc = numericoidValidate( NULL, &comp ); 4529 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) { 4530 rc = integerValidate( NULL, &comp ); 4531 } else { 4532 rc = LDAP_INVALID_SYNTAX; 4533 } 4534 4535 4536 if( rc == LDAP_SUCCESS ) { 4537 ber_dupbv_x( normalized, &comp, ctx ); 4538 } 4539 4540 return rc; 4541 } 4542 4543 static char *country_gen_syn[] = { 4544 "1.3.6.1.4.1.1466.115.121.1.15", 4545 "1.3.6.1.4.1.1466.115.121.1.26", 4546 "1.3.6.1.4.1.1466.115.121.1.44", 4547 NULL 4548 }; 4549 4550 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " 4551 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " 4552 4553 static slap_syntax_defs_rec syntax_defs[] = { 4554 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " 4555 X_BINARY X_NOT_H_R ")", 4556 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL}, 4557 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")", 4558 0, NULL, NULL, NULL}, 4559 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", 4560 0, NULL, NULL, NULL}, 4561 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " 4562 X_NOT_H_R ")", 4563 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 4564 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " 4565 X_NOT_H_R ")", 4566 SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 4567 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", 4568 0, NULL, bitStringValidate, NULL }, 4569 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", 4570 0, NULL, booleanValidate, NULL}, 4571 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " 4572 X_BINARY X_NOT_H_R ")", 4573 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4574 NULL, certificateValidate, NULL}, 4575 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " 4576 X_BINARY X_NOT_H_R ")", 4577 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4578 NULL, certificateListValidate, NULL}, 4579 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " 4580 X_BINARY X_NOT_H_R ")", 4581 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4582 NULL, sequenceValidate, NULL}, 4583 #if 0 /* need to go __after__ printableString */ 4584 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 4585 0, "1.3.6.1.4.1.1466.115.121.1.44", 4586 countryStringValidate, NULL}, 4587 #endif 4588 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", 4589 0, NULL, dnValidate, dnPretty}, 4590 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )", 4591 0, NULL, rdnValidate, rdnPretty}, 4592 #ifdef LDAP_COMP_MATCH 4593 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", 4594 0, NULL, allComponentsValidate, NULL}, 4595 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ", 4596 0, NULL, componentFilterValidate, NULL}, 4597 #endif 4598 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )", 4599 0, NULL, NULL, NULL}, 4600 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", 4601 0, NULL, deliveryMethodValidate, NULL}, 4602 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", 4603 0, NULL, UTF8StringValidate, NULL}, 4604 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", 4605 0, NULL, NULL, NULL}, 4606 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", 4607 0, NULL, NULL, NULL}, 4608 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )", 4609 0, NULL, NULL, NULL}, 4610 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )", 4611 0, NULL, NULL, NULL}, 4612 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", 4613 0, NULL, NULL, NULL}, 4614 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", 4615 0, NULL, printablesStringValidate, NULL}, 4616 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")", 4617 SLAP_SYNTAX_BLOB, NULL, NULL, NULL}, 4618 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", 4619 0, NULL, generalizedTimeValidate, NULL}, 4620 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", 4621 0, NULL, NULL, NULL}, 4622 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", 4623 0, NULL, IA5StringValidate, NULL}, 4624 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", 4625 0, NULL, integerValidate, NULL}, 4626 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")", 4627 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 4628 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )", 4629 0, NULL, NULL, NULL}, 4630 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", 4631 0, NULL, NULL, NULL}, 4632 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", 4633 0, NULL, NULL, NULL}, 4634 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", 4635 0, NULL, NULL, NULL}, 4636 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", 4637 0, NULL, NULL, NULL}, 4638 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", 4639 0, NULL, nameUIDValidate, nameUIDPretty }, 4640 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", 4641 0, NULL, NULL, NULL}, 4642 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", 4643 0, NULL, numericStringValidate, NULL}, 4644 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", 4645 0, NULL, NULL, NULL}, 4646 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", 4647 0, NULL, numericoidValidate, NULL}, 4648 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", 4649 0, NULL, IA5StringValidate, NULL}, 4650 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", 4651 0, NULL, blobValidate, NULL}, 4652 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", 4653 0, NULL, UTF8StringValidate, NULL}, 4654 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", 4655 0, NULL, NULL, NULL}, 4656 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", 4657 0, NULL, NULL, NULL}, 4658 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", 4659 0, NULL, printableStringValidate, NULL}, 4660 /* moved here because now depends on Directory String, IA5 String 4661 * and Printable String */ 4662 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 4663 0, country_gen_syn, countryStringValidate, NULL}, 4664 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )", 4665 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */ 4666 0, NULL, subtreeSpecificationValidate, NULL}, 4667 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " 4668 X_BINARY X_NOT_H_R ")", 4669 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 4670 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", 4671 0, NULL, printableStringValidate, NULL}, 4672 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", 4673 0, NULL, NULL, NULL}, 4674 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", 4675 0, NULL, printablesStringValidate, NULL}, 4676 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 4677 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", 4678 0, NULL, utcTimeValidate, NULL}, 4679 #endif 4680 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", 4681 0, NULL, NULL, NULL}, 4682 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )", 4683 0, NULL, NULL, NULL}, 4684 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )", 4685 0, NULL, NULL, NULL}, 4686 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )", 4687 0, NULL, NULL, NULL}, 4688 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", 4689 0, NULL, NULL, NULL}, 4690 4691 /* RFC 2307 NIS Syntaxes */ 4692 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )", 4693 0, NULL, nisNetgroupTripleValidate, NULL}, 4694 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", 4695 0, NULL, bootParameterValidate, NULL}, 4696 4697 /* draft-zeilenga-ldap-x509 */ 4698 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )", 4699 SLAP_SYNTAX_HIDE, NULL, 4700 serialNumberAndIssuerValidate, 4701 serialNumberAndIssuerPretty}, 4702 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )", 4703 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4704 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )", 4705 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4706 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )", 4707 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4708 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )", 4709 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4710 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )", 4711 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4712 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )", 4713 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4714 4715 #ifdef SLAPD_AUTHPASSWD 4716 /* needs updating */ 4717 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )", 4718 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4719 #endif 4720 4721 {"( 1.3.6.1.1.16.1 DESC 'UUID' )", 4722 0, NULL, UUIDValidate, UUIDPretty}, 4723 4724 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )", 4725 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty }, 4726 4727 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )", 4728 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty }, 4729 4730 /* OpenLDAP Void Syntax */ 4731 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , 4732 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL}, 4733 4734 /* FIXME: OID is unused, but not registered yet */ 4735 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )", 4736 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty}, 4737 4738 {NULL, 0, NULL, NULL, NULL} 4739 }; 4740 4741 char *csnSIDMatchSyntaxes[] = { 4742 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */, 4743 NULL 4744 }; 4745 char *certificateExactMatchSyntaxes[] = { 4746 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 4747 NULL 4748 }; 4749 #ifdef LDAP_COMP_MATCH 4750 char *componentFilterMatchSyntaxes[] = { 4751 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 4752 NULL 4753 }; 4754 #endif 4755 char *directoryStringSyntaxes[] = { 4756 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */, 4757 NULL 4758 }; 4759 char *integerFirstComponentMatchSyntaxes[] = { 4760 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */, 4761 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */, 4762 NULL 4763 }; 4764 char *objectIdentifierFirstComponentMatchSyntaxes[] = { 4765 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */, 4766 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */, 4767 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */, 4768 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */, 4769 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */, 4770 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */, 4771 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */, 4772 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */, 4773 NULL 4774 }; 4775 4776 /* 4777 * Other matching rules in X.520 that we do not use (yet): 4778 * 4779 * 2.5.13.25 uTCTimeMatch 4780 * 2.5.13.26 uTCTimeOrderingMatch 4781 * 2.5.13.31* directoryStringFirstComponentMatch 4782 * 2.5.13.32* wordMatch 4783 * 2.5.13.33* keywordMatch 4784 * 2.5.13.36+ certificatePairExactMatch 4785 * 2.5.13.37+ certificatePairMatch 4786 * 2.5.13.38+ certificateListExactMatch 4787 * 2.5.13.39+ certificateListMatch 4788 * 2.5.13.40+ algorithmIdentifierMatch 4789 * 2.5.13.41* storedPrefixMatch 4790 * 2.5.13.42 attributeCertificateMatch 4791 * 2.5.13.43 readerAndKeyIDMatch 4792 * 2.5.13.44 attributeIntegrityMatch 4793 * 4794 * (*) described in RFC 3698 (LDAP: Additional Matching Rules) 4795 * (+) described in draft-zeilenga-ldap-x509 4796 */ 4797 static slap_mrule_defs_rec mrule_defs[] = { 4798 /* 4799 * EQUALITY matching rules must be listed after associated APPROX 4800 * matching rules. So, we list all APPROX matching rules first. 4801 */ 4802 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' " 4803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4804 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 4805 NULL, NULL, directoryStringApproxMatch, 4806 directoryStringApproxIndexer, directoryStringApproxFilter, 4807 NULL}, 4808 4809 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' " 4810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 4811 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 4812 NULL, NULL, IA5StringApproxMatch, 4813 IA5StringApproxIndexer, IA5StringApproxFilter, 4814 NULL}, 4815 4816 /* 4817 * Other matching rules 4818 */ 4819 4820 {"( 2.5.13.0 NAME 'objectIdentifierMatch' " 4821 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 4822 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4823 NULL, NULL, octetStringMatch, 4824 octetStringIndexer, octetStringFilter, 4825 NULL }, 4826 4827 {"( 2.5.13.1 NAME 'distinguishedNameMatch' " 4828 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4829 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4830 NULL, dnNormalize, dnMatch, 4831 octetStringIndexer, octetStringFilter, 4832 NULL }, 4833 4834 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' " 4835 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4836 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4837 NULL, dnNormalize, dnRelativeMatch, 4838 NULL, NULL, 4839 NULL }, 4840 4841 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' " 4842 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4843 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4844 NULL, dnNormalize, dnRelativeMatch, 4845 NULL, NULL, 4846 NULL }, 4847 4848 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' " 4849 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4850 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4851 NULL, dnNormalize, dnRelativeMatch, 4852 NULL, NULL, 4853 NULL }, 4854 4855 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' " 4856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4857 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4858 NULL, dnNormalize, dnRelativeMatch, 4859 NULL, NULL, 4860 NULL }, 4861 4862 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' " 4863 "SYNTAX 1.2.36.79672281.1.5.0 )", 4864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4865 NULL, rdnNormalize, rdnMatch, 4866 octetStringIndexer, octetStringFilter, 4867 NULL }, 4868 4869 #ifdef LDAP_COMP_MATCH 4870 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' " 4871 "SYNTAX 1.2.36.79672281.1.5.2 )", 4872 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes, 4873 NULL, NULL , componentFilterMatch, 4874 octetStringIndexer, octetStringFilter, 4875 NULL }, 4876 4877 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' " 4878 "SYNTAX 1.2.36.79672281.1.5.3 )", 4879 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 4880 NULL, NULL , allComponentsMatch, 4881 octetStringIndexer, octetStringFilter, 4882 NULL }, 4883 4884 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' " 4885 "SYNTAX 1.2.36.79672281.1.5.3 )", 4886 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 4887 NULL, NULL , directoryComponentsMatch, 4888 octetStringIndexer, octetStringFilter, 4889 NULL }, 4890 #endif 4891 4892 {"( 2.5.13.2 NAME 'caseIgnoreMatch' " 4893 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4894 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 4895 NULL, UTF8StringNormalize, octetStringMatch, 4896 octetStringIndexer, octetStringFilter, 4897 directoryStringApproxMatchOID }, 4898 4899 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' " 4900 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4901 SLAP_MR_ORDERING, directoryStringSyntaxes, 4902 NULL, UTF8StringNormalize, octetStringOrderingMatch, 4903 NULL, NULL, 4904 "caseIgnoreMatch" }, 4905 4906 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " 4907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4908 SLAP_MR_SUBSTR, directoryStringSyntaxes, 4909 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 4910 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4911 "caseIgnoreMatch" }, 4912 4913 {"( 2.5.13.5 NAME 'caseExactMatch' " 4914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4915 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 4916 NULL, UTF8StringNormalize, octetStringMatch, 4917 octetStringIndexer, octetStringFilter, 4918 directoryStringApproxMatchOID }, 4919 4920 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' " 4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4922 SLAP_MR_ORDERING, directoryStringSyntaxes, 4923 NULL, UTF8StringNormalize, octetStringOrderingMatch, 4924 NULL, NULL, 4925 "caseExactMatch" }, 4926 4927 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " 4928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4929 SLAP_MR_SUBSTR, directoryStringSyntaxes, 4930 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 4931 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4932 "caseExactMatch" }, 4933 4934 {"( 2.5.13.8 NAME 'numericStringMatch' " 4935 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 4936 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4937 NULL, numericStringNormalize, octetStringMatch, 4938 octetStringIndexer, octetStringFilter, 4939 NULL }, 4940 4941 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' " 4942 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 4943 SLAP_MR_ORDERING, NULL, 4944 NULL, numericStringNormalize, octetStringOrderingMatch, 4945 NULL, NULL, 4946 "numericStringMatch" }, 4947 4948 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' " 4949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4950 SLAP_MR_SUBSTR, NULL, 4951 NULL, numericStringNormalize, octetStringSubstringsMatch, 4952 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4953 "numericStringMatch" }, 4954 4955 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' " 4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", 4957 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4958 NULL, NULL, NULL, NULL, NULL, NULL }, 4959 4960 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' " 4961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4962 SLAP_MR_SUBSTR, NULL, 4963 NULL, NULL, NULL, NULL, NULL, 4964 "caseIgnoreListMatch" }, 4965 4966 {"( 2.5.13.13 NAME 'booleanMatch' " 4967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )", 4968 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4969 NULL, NULL, booleanMatch, 4970 octetStringIndexer, octetStringFilter, 4971 NULL }, 4972 4973 {"( 2.5.13.14 NAME 'integerMatch' " 4974 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 4975 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 4976 NULL, NULL, integerMatch, 4977 integerIndexer, integerFilter, 4978 NULL }, 4979 4980 {"( 2.5.13.15 NAME 'integerOrderingMatch' " 4981 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 4982 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 4983 NULL, NULL, integerMatch, 4984 NULL, NULL, 4985 "integerMatch" }, 4986 4987 {"( 2.5.13.16 NAME 'bitStringMatch' " 4988 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", 4989 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4990 NULL, NULL, octetStringMatch, 4991 octetStringIndexer, octetStringFilter, 4992 NULL }, 4993 4994 {"( 2.5.13.17 NAME 'octetStringMatch' " 4995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 4996 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4997 NULL, NULL, octetStringMatch, 4998 octetStringIndexer, octetStringFilter, 4999 NULL }, 5000 5001 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' " 5002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5003 SLAP_MR_ORDERING, NULL, 5004 NULL, NULL, octetStringOrderingMatch, 5005 NULL, NULL, 5006 "octetStringMatch" }, 5007 5008 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' " 5009 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5010 SLAP_MR_SUBSTR, NULL, 5011 NULL, NULL, octetStringSubstringsMatch, 5012 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5013 "octetStringMatch" }, 5014 5015 {"( 2.5.13.20 NAME 'telephoneNumberMatch' " 5016 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", 5017 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5018 NULL, 5019 telephoneNumberNormalize, octetStringMatch, 5020 octetStringIndexer, octetStringFilter, 5021 NULL }, 5022 5023 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' " 5024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 5025 SLAP_MR_SUBSTR, NULL, 5026 NULL, telephoneNumberNormalize, octetStringSubstringsMatch, 5027 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5028 "telephoneNumberMatch" }, 5029 5030 {"( 2.5.13.22 NAME 'presentationAddressMatch' " 5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", 5032 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5033 NULL, NULL, NULL, NULL, NULL, NULL }, 5034 5035 {"( 2.5.13.23 NAME 'uniqueMemberMatch' " 5036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", 5037 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5038 NULL, uniqueMemberNormalize, uniqueMemberMatch, 5039 uniqueMemberIndexer, uniqueMemberFilter, 5040 NULL }, 5041 5042 {"( 2.5.13.24 NAME 'protocolInformationMatch' " 5043 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", 5044 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5045 NULL, NULL, NULL, NULL, NULL, NULL }, 5046 5047 {"( 2.5.13.27 NAME 'generalizedTimeMatch' " 5048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 5049 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 5050 NULL, generalizedTimeNormalize, octetStringMatch, 5051 generalizedTimeIndexer, generalizedTimeFilter, 5052 NULL }, 5053 5054 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " 5055 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 5056 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 5057 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch, 5058 NULL, NULL, 5059 "generalizedTimeMatch" }, 5060 5061 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' " 5062 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5063 SLAP_MR_EQUALITY | SLAP_MR_EXT, 5064 integerFirstComponentMatchSyntaxes, 5065 NULL, firstComponentNormalize, integerMatch, 5066 octetStringIndexer, octetStringFilter, 5067 NULL }, 5068 5069 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' " 5070 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 5071 SLAP_MR_EQUALITY | SLAP_MR_EXT, 5072 objectIdentifierFirstComponentMatchSyntaxes, 5073 NULL, firstComponentNormalize, octetStringMatch, 5074 octetStringIndexer, octetStringFilter, 5075 NULL }, 5076 5077 {"( 2.5.13.34 NAME 'certificateExactMatch' " 5078 "SYNTAX 1.3.6.1.1.15.1 )", 5079 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, 5080 NULL, certificateExactNormalize, octetStringMatch, 5081 octetStringIndexer, octetStringFilter, 5082 NULL }, 5083 5084 {"( 2.5.13.35 NAME 'certificateMatch' " 5085 "SYNTAX 1.3.6.1.1.15.2 )", 5086 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5087 NULL, NULL, NULL, NULL, NULL, 5088 NULL }, 5089 5090 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " 5091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5092 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5093 NULL, IA5StringNormalize, octetStringMatch, 5094 octetStringIndexer, octetStringFilter, 5095 IA5StringApproxMatchOID }, 5096 5097 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' " 5098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5099 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5100 NULL, IA5StringNormalize, octetStringMatch, 5101 octetStringIndexer, octetStringFilter, 5102 IA5StringApproxMatchOID }, 5103 5104 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' " 5105 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5106 SLAP_MR_SUBSTR, NULL, 5107 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 5108 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5109 "caseIgnoreIA5Match" }, 5110 5111 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' " 5112 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5113 SLAP_MR_SUBSTR, NULL, 5114 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 5115 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5116 "caseExactIA5Match" }, 5117 5118 #ifdef SLAPD_AUTHPASSWD 5119 /* needs updating */ 5120 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' " 5121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5122 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 5123 NULL, NULL, authPasswordMatch, 5124 NULL, NULL, 5125 NULL}, 5126 #endif 5127 5128 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' " 5129 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5130 SLAP_MR_EXT, NULL, 5131 NULL, NULL, integerBitAndMatch, 5132 NULL, NULL, 5133 "integerMatch" }, 5134 5135 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' " 5136 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5137 SLAP_MR_EXT, NULL, 5138 NULL, NULL, integerBitOrMatch, 5139 NULL, NULL, 5140 "integerMatch" }, 5141 5142 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' " 5143 "SYNTAX 1.3.6.1.1.16.1 )", 5144 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL, 5145 NULL, UUIDNormalize, octetStringMatch, 5146 octetStringIndexer, octetStringFilter, 5147 NULL}, 5148 5149 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' " 5150 "SYNTAX 1.3.6.1.1.16.1 )", 5151 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL, 5152 NULL, UUIDNormalize, octetStringOrderingMatch, 5153 octetStringIndexer, octetStringFilter, 5154 "UUIDMatch"}, 5155 5156 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' " 5157 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 5158 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL, 5159 NULL, csnNormalize, csnMatch, 5160 csnIndexer, csnFilter, 5161 NULL}, 5162 5163 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' " 5164 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 5165 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 5166 NULL, NULL, csnOrderingMatch, 5167 NULL, NULL, 5168 "CSNMatch" }, 5169 5170 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' " 5171 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )", 5172 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes, 5173 NULL, csnSidNormalize, octetStringMatch, 5174 octetStringIndexer, octetStringFilter, 5175 NULL }, 5176 5177 /* FIXME: OID is unused, but not registered yet */ 5178 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' " 5179 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", 5180 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 5181 NULL, authzNormalize, authzMatch, 5182 NULL, NULL, 5183 NULL}, 5184 5185 {NULL, SLAP_MR_NONE, NULL, 5186 NULL, NULL, NULL, NULL, NULL, 5187 NULL } 5188 }; 5189 5190 int 5191 slap_schema_init( void ) 5192 { 5193 int res; 5194 int i; 5195 5196 /* we should only be called once (from main) */ 5197 assert( schema_init_done == 0 ); 5198 5199 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { 5200 res = register_syntax( &syntax_defs[i] ); 5201 5202 if ( res ) { 5203 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n", 5204 syntax_defs[i].sd_desc ); 5205 return LDAP_OTHER; 5206 } 5207 } 5208 5209 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) { 5210 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE && 5211 mrule_defs[i].mrd_compat_syntaxes == NULL ) 5212 { 5213 fprintf( stderr, 5214 "slap_schema_init: Ignoring unusable matching rule %s\n", 5215 mrule_defs[i].mrd_desc ); 5216 continue; 5217 } 5218 5219 res = register_matching_rule( &mrule_defs[i] ); 5220 5221 if ( res ) { 5222 fprintf( stderr, 5223 "slap_schema_init: Error registering matching rule %s\n", 5224 mrule_defs[i].mrd_desc ); 5225 return LDAP_OTHER; 5226 } 5227 } 5228 5229 res = slap_schema_load(); 5230 schema_init_done = 1; 5231 return res; 5232 } 5233 5234 void 5235 schema_destroy( void ) 5236 { 5237 oidm_destroy(); 5238 oc_destroy(); 5239 at_destroy(); 5240 mr_destroy(); 5241 mru_destroy(); 5242 syn_destroy(); 5243 5244 if( schema_init_done ) { 5245 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex ); 5246 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex ); 5247 } 5248 } 5249