1 /* schema_init.c - init builtin schema */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/schema_init.c,v 1.386.2.22 2008/07/10 00:02:48 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 keys[1].bv_len = 0; 2277 keys[1].bv_val = NULL; 2278 2279 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1 2280 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2281 if ( iv.bv_len > (int) sizeof(ibuf) ) { 2282 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx ); 2283 } else { 2284 iv.bv_val = ibuf; 2285 iv.bv_len = sizeof(ibuf); 2286 } 2287 2288 rc = integerVal2Key( value, keys, &iv, ctx ); 2289 if ( rc == 0 ) 2290 *keysp = keys; 2291 2292 if ( iv.bv_val != ibuf ) { 2293 slap_sl_free( iv.bv_val, ctx ); 2294 } 2295 return rc; 2296 } 2297 2298 static int 2299 countryStringValidate( 2300 Syntax *syntax, 2301 struct berval *val ) 2302 { 2303 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX; 2304 2305 if( !SLAP_PRINTABLE(val->bv_val[0]) ) { 2306 return LDAP_INVALID_SYNTAX; 2307 } 2308 if( !SLAP_PRINTABLE(val->bv_val[1]) ) { 2309 return LDAP_INVALID_SYNTAX; 2310 } 2311 2312 return LDAP_SUCCESS; 2313 } 2314 2315 static int 2316 printableStringValidate( 2317 Syntax *syntax, 2318 struct berval *val ) 2319 { 2320 ber_len_t i; 2321 2322 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2323 2324 for(i=0; i < val->bv_len; i++) { 2325 if( !SLAP_PRINTABLE(val->bv_val[i]) ) { 2326 return LDAP_INVALID_SYNTAX; 2327 } 2328 } 2329 2330 return LDAP_SUCCESS; 2331 } 2332 2333 static int 2334 printablesStringValidate( 2335 Syntax *syntax, 2336 struct berval *val ) 2337 { 2338 ber_len_t i, len; 2339 2340 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2341 2342 for(i=0,len=0; i < val->bv_len; i++) { 2343 int c = val->bv_val[i]; 2344 2345 if( c == '$' ) { 2346 if( len == 0 ) { 2347 return LDAP_INVALID_SYNTAX; 2348 } 2349 len = 0; 2350 2351 } else if ( SLAP_PRINTABLE(c) ) { 2352 len++; 2353 } else { 2354 return LDAP_INVALID_SYNTAX; 2355 } 2356 } 2357 2358 if( len == 0 ) { 2359 return LDAP_INVALID_SYNTAX; 2360 } 2361 2362 return LDAP_SUCCESS; 2363 } 2364 2365 static int 2366 IA5StringValidate( 2367 Syntax *syntax, 2368 struct berval *val ) 2369 { 2370 ber_len_t i; 2371 2372 for(i=0; i < val->bv_len; i++) { 2373 if( !LDAP_ASCII(val->bv_val[i]) ) { 2374 return LDAP_INVALID_SYNTAX; 2375 } 2376 } 2377 2378 return LDAP_SUCCESS; 2379 } 2380 2381 static int 2382 IA5StringNormalize( 2383 slap_mask_t use, 2384 Syntax *syntax, 2385 MatchingRule *mr, 2386 struct berval *val, 2387 struct berval *normalized, 2388 void *ctx ) 2389 { 2390 char *p, *q; 2391 int casefold = !SLAP_MR_ASSOCIATED( mr, 2392 slap_schema.si_mr_caseExactIA5Match ); 2393 2394 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 2395 2396 p = val->bv_val; 2397 2398 /* Ignore initial whitespace */ 2399 while ( ASCII_SPACE( *p ) ) p++; 2400 2401 normalized->bv_len = val->bv_len - ( p - val->bv_val ); 2402 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2403 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len ); 2404 normalized->bv_val[normalized->bv_len] = '\0'; 2405 2406 p = q = normalized->bv_val; 2407 2408 while ( *p ) { 2409 if ( ASCII_SPACE( *p ) ) { 2410 *q++ = *p++; 2411 2412 /* Ignore the extra whitespace */ 2413 while ( ASCII_SPACE( *p ) ) { 2414 p++; 2415 } 2416 2417 } else if ( casefold ) { 2418 /* Most IA5 rules require casefolding */ 2419 *q++ = TOLOWER(*p); p++; 2420 2421 } else { 2422 *q++ = *p++; 2423 } 2424 } 2425 2426 assert( normalized->bv_val <= p ); 2427 assert( q <= p ); 2428 2429 /* 2430 * If the string ended in space, backup the pointer one 2431 * position. One is enough because the above loop collapsed 2432 * all whitespace to a single space. 2433 */ 2434 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q; 2435 2436 /* null terminate */ 2437 *q = '\0'; 2438 2439 normalized->bv_len = q - normalized->bv_val; 2440 2441 return LDAP_SUCCESS; 2442 } 2443 2444 static int 2445 UUIDValidate( 2446 Syntax *syntax, 2447 struct berval *in ) 2448 { 2449 int i; 2450 if( in->bv_len != 36 ) { 2451 return LDAP_INVALID_SYNTAX; 2452 } 2453 2454 for( i=0; i<36; i++ ) { 2455 switch(i) { 2456 case 8: 2457 case 13: 2458 case 18: 2459 case 23: 2460 if( in->bv_val[i] != '-' ) { 2461 return LDAP_INVALID_SYNTAX; 2462 } 2463 break; 2464 default: 2465 if( !ASCII_HEX( in->bv_val[i]) ) { 2466 return LDAP_INVALID_SYNTAX; 2467 } 2468 } 2469 } 2470 2471 return LDAP_SUCCESS; 2472 } 2473 2474 static int 2475 UUIDPretty( 2476 Syntax *syntax, 2477 struct berval *in, 2478 struct berval *out, 2479 void *ctx ) 2480 { 2481 int i; 2482 int rc=LDAP_INVALID_SYNTAX; 2483 2484 assert( in != NULL ); 2485 assert( out != NULL ); 2486 2487 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX; 2488 2489 out->bv_len = 36; 2490 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 2491 2492 for( i=0; i<36; i++ ) { 2493 switch(i) { 2494 case 8: 2495 case 13: 2496 case 18: 2497 case 23: 2498 if( in->bv_val[i] != '-' ) { 2499 goto handle_error; 2500 } 2501 out->bv_val[i] = '-'; 2502 break; 2503 2504 default: 2505 if( !ASCII_HEX( in->bv_val[i]) ) { 2506 goto handle_error; 2507 } 2508 out->bv_val[i] = TOLOWER( in->bv_val[i] ); 2509 } 2510 } 2511 2512 rc = LDAP_SUCCESS; 2513 out->bv_val[ out->bv_len ] = '\0'; 2514 2515 if( 0 ) { 2516 handle_error: 2517 slap_sl_free( out->bv_val, ctx ); 2518 out->bv_val = NULL; 2519 } 2520 2521 return rc; 2522 } 2523 2524 int 2525 UUIDNormalize( 2526 slap_mask_t usage, 2527 Syntax *syntax, 2528 MatchingRule *mr, 2529 struct berval *val, 2530 struct berval *normalized, 2531 void *ctx ) 2532 { 2533 unsigned char octet = '\0'; 2534 int i; 2535 int j; 2536 2537 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) { 2538 /* NOTE: must be a normalized UUID */ 2539 assert( val->bv_len == 16 ); 2540 2541 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx ); 2542 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val, 2543 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE ); 2544 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) ); 2545 2546 return LDAP_SUCCESS; 2547 } 2548 2549 normalized->bv_len = 16; 2550 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2551 2552 for( i=0, j=0; i<36; i++ ) { 2553 unsigned char nibble; 2554 if( val->bv_val[i] == '-' ) { 2555 continue; 2556 2557 } else if( ASCII_DIGIT( val->bv_val[i] ) ) { 2558 nibble = val->bv_val[i] - '0'; 2559 2560 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) { 2561 nibble = val->bv_val[i] - ('a'-10); 2562 2563 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) { 2564 nibble = val->bv_val[i] - ('A'-10); 2565 2566 } else { 2567 slap_sl_free( normalized->bv_val, ctx ); 2568 return LDAP_INVALID_SYNTAX; 2569 } 2570 2571 if( j & 1 ) { 2572 octet |= nibble; 2573 normalized->bv_val[j>>1] = octet; 2574 } else { 2575 octet = nibble << 4; 2576 } 2577 j++; 2578 } 2579 2580 normalized->bv_val[normalized->bv_len] = 0; 2581 return LDAP_SUCCESS; 2582 } 2583 2584 2585 2586 int 2587 numericStringValidate( 2588 Syntax *syntax, 2589 struct berval *in ) 2590 { 2591 ber_len_t i; 2592 2593 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX; 2594 2595 for(i=0; i < in->bv_len; i++) { 2596 if( !SLAP_NUMERIC(in->bv_val[i]) ) { 2597 return LDAP_INVALID_SYNTAX; 2598 } 2599 } 2600 2601 return LDAP_SUCCESS; 2602 } 2603 2604 static int 2605 numericStringNormalize( 2606 slap_mask_t usage, 2607 Syntax *syntax, 2608 MatchingRule *mr, 2609 struct berval *val, 2610 struct berval *normalized, 2611 void *ctx ) 2612 { 2613 /* removal all spaces */ 2614 char *p, *q; 2615 2616 assert( !BER_BVISEMPTY( val ) ); 2617 2618 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 2619 2620 p = val->bv_val; 2621 q = normalized->bv_val; 2622 2623 while ( *p ) { 2624 if ( ASCII_SPACE( *p ) ) { 2625 /* Ignore whitespace */ 2626 p++; 2627 } else { 2628 *q++ = *p++; 2629 } 2630 } 2631 2632 /* we should have copied no more than is in val */ 2633 assert( (q - normalized->bv_val) <= (p - val->bv_val) ); 2634 2635 /* null terminate */ 2636 *q = '\0'; 2637 2638 normalized->bv_len = q - normalized->bv_val; 2639 2640 if( BER_BVISEMPTY( normalized ) ) { 2641 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx ); 2642 normalized->bv_val[0] = ' '; 2643 normalized->bv_val[1] = '\0'; 2644 normalized->bv_len = 1; 2645 } 2646 2647 return LDAP_SUCCESS; 2648 } 2649 2650 /* 2651 * Integer conversion macros that will use the largest available 2652 * type. 2653 */ 2654 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) 2655 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) 2656 # define SLAP_LONG long long 2657 #else 2658 # define SLAP_STRTOL(n,e,b) strtol(n,e,b) 2659 # define SLAP_LONG long 2660 #endif /* HAVE_STRTOLL ... */ 2661 2662 static int 2663 integerBitAndMatch( 2664 int *matchp, 2665 slap_mask_t flags, 2666 Syntax *syntax, 2667 MatchingRule *mr, 2668 struct berval *value, 2669 void *assertedValue ) 2670 { 2671 SLAP_LONG lValue, lAssertedValue; 2672 2673 errno = 0; 2674 /* safe to assume integers are NUL terminated? */ 2675 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 2676 if( errno == ERANGE ) 2677 { 2678 return LDAP_CONSTRAINT_VIOLATION; 2679 } 2680 2681 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, 2682 NULL, 10); 2683 if( errno == ERANGE ) 2684 { 2685 return LDAP_CONSTRAINT_VIOLATION; 2686 } 2687 2688 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1; 2689 return LDAP_SUCCESS; 2690 } 2691 2692 static int 2693 integerBitOrMatch( 2694 int *matchp, 2695 slap_mask_t flags, 2696 Syntax *syntax, 2697 MatchingRule *mr, 2698 struct berval *value, 2699 void *assertedValue ) 2700 { 2701 SLAP_LONG lValue, lAssertedValue; 2702 2703 errno = 0; 2704 /* safe to assume integers are NUL terminated? */ 2705 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 2706 if( errno == ERANGE ) 2707 { 2708 return LDAP_CONSTRAINT_VIOLATION; 2709 } 2710 2711 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, 2712 NULL, 10); 2713 if( errno == ERANGE ) 2714 { 2715 return LDAP_CONSTRAINT_VIOLATION; 2716 } 2717 2718 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1; 2719 return LDAP_SUCCESS; 2720 } 2721 2722 static int 2723 serialNumberAndIssuerCheck( 2724 struct berval *in, 2725 struct berval *sn, 2726 struct berval *is, 2727 void *ctx 2728 ) 2729 { 2730 int is_hex = 0, n; 2731 2732 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 2733 2734 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 2735 /* Parse old format */ 2736 is->bv_val = ber_bvchr( in, '$' ); 2737 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX; 2738 2739 sn->bv_val = in->bv_val; 2740 sn->bv_len = is->bv_val - in->bv_val; 2741 2742 is->bv_val++; 2743 is->bv_len = in->bv_len - (sn->bv_len + 1); 2744 2745 /* eat leading zeros */ 2746 for( n=0; n < (sn->bv_len-1); n++ ) { 2747 if( sn->bv_val[n] != '0' ) break; 2748 } 2749 sn->bv_val += n; 2750 sn->bv_len -= n; 2751 2752 for( n=0; n < sn->bv_len; n++ ) { 2753 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX; 2754 } 2755 2756 } else { 2757 /* Parse GSER format */ 2758 int havesn = 0, haveissuer = 0, numdquotes = 0; 2759 struct berval x = *in; 2760 struct berval ni; 2761 x.bv_val++; 2762 x.bv_len-=2; 2763 2764 /* eat leading spaces */ 2765 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2766 /* empty */; 2767 } 2768 2769 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) { 2770 return LDAP_INVALID_SYNTAX; 2771 } 2772 2773 /* should be at issuer or serialNumber NamedValue */ 2774 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) { 2775 /* parse issuer */ 2776 x.bv_val += STRLENOF("issuer"); 2777 x.bv_len -= STRLENOF("issuer"); 2778 2779 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2780 x.bv_val++; x.bv_len--; 2781 2782 /* eat leading spaces */ 2783 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2784 /* empty */; 2785 } 2786 2787 /* For backward compatibility, this part is optional */ 2788 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { 2789 x.bv_val += STRLENOF("rdnSequence:"); 2790 x.bv_len -= STRLENOF("rdnSequence:"); 2791 } 2792 2793 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 2794 x.bv_val++; x.bv_len--; 2795 2796 is->bv_val = x.bv_val; 2797 is->bv_len = 0; 2798 2799 for( ; is->bv_len < x.bv_len; ) { 2800 if ( is->bv_val[is->bv_len] != '"' ) { 2801 is->bv_len++; 2802 continue; 2803 } 2804 if ( is->bv_val[is->bv_len+1] == '"' ) { 2805 /* double dquote */ 2806 is->bv_len+=2; 2807 continue; 2808 } 2809 break; 2810 } 2811 x.bv_val += is->bv_len+1; 2812 x.bv_len -= is->bv_len+1; 2813 2814 if ( x.bv_len < STRLENOF(",serialNumber 0")) { 2815 return LDAP_INVALID_SYNTAX; 2816 } 2817 2818 haveissuer++; 2819 2820 } else if( strncasecmp( x.bv_val, "serialNumber", 2821 STRLENOF("serialNumber")) == 0 ) 2822 { 2823 /* parse serialNumber */ 2824 int neg = 0; 2825 char first = '\0'; 2826 int extra = 0; 2827 2828 x.bv_val += STRLENOF("serialNumber"); 2829 x.bv_len -= STRLENOF("serialNumber"); 2830 2831 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2832 x.bv_val++; x.bv_len--; 2833 2834 /* eat leading spaces */ 2835 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2836 /* empty */; 2837 } 2838 2839 sn->bv_val = x.bv_val; 2840 sn->bv_len = 0; 2841 2842 if( sn->bv_val[0] == '-' ) { 2843 neg++; 2844 sn->bv_len++; 2845 } 2846 2847 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || 2848 sn->bv_val[1] == 'X' )) 2849 { 2850 is_hex = 1; 2851 first = sn->bv_val[2]; 2852 extra = 2; 2853 2854 sn->bv_len += STRLENOF("0x"); 2855 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2856 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2857 } 2858 2859 } else if ( sn->bv_val[0] == '\'' ) { 2860 first = sn->bv_val[1]; 2861 extra = 3; 2862 2863 sn->bv_len += STRLENOF("'"); 2864 2865 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2866 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2867 } 2868 if ( sn->bv_val[sn->bv_len] == '\'' && 2869 sn->bv_val[sn->bv_len + 1] == 'H' ) 2870 { 2871 sn->bv_len += STRLENOF("'H"); 2872 is_hex = 1; 2873 2874 } else { 2875 return LDAP_INVALID_SYNTAX; 2876 } 2877 2878 } else { 2879 first = sn->bv_val[0]; 2880 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2881 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; 2882 } 2883 } 2884 2885 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; 2886 if (( sn->bv_len > extra+1+neg ) && ( first == '0' )) { 2887 return LDAP_INVALID_SYNTAX; 2888 } 2889 2890 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len; 2891 2892 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) { 2893 return LDAP_INVALID_SYNTAX; 2894 } 2895 2896 havesn++; 2897 2898 } else return LDAP_INVALID_SYNTAX; 2899 2900 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX; 2901 x.bv_val++; x.bv_len--; 2902 2903 /* eat spaces */ 2904 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2905 /* empty */; 2906 } 2907 2908 /* should be at remaining NamedValue */ 2909 if( !haveissuer && (strncasecmp( x.bv_val, "issuer", 2910 STRLENOF("issuer" )) == 0 )) 2911 { 2912 /* parse issuer */ 2913 x.bv_val += STRLENOF("issuer"); 2914 x.bv_len -= STRLENOF("issuer"); 2915 2916 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2917 x.bv_val++; x.bv_len--; 2918 2919 /* eat leading spaces */ 2920 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 2921 /* empty */; 2922 } 2923 2924 /* For backward compatibility, this part is optional */ 2925 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { 2926 x.bv_val += STRLENOF("rdnSequence:"); 2927 x.bv_len -= STRLENOF("rdnSequence:"); 2928 } 2929 2930 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 2931 x.bv_val++; x.bv_len--; 2932 2933 is->bv_val = x.bv_val; 2934 is->bv_len = 0; 2935 2936 for( ; is->bv_len < x.bv_len; ) { 2937 if ( is->bv_val[is->bv_len] != '"' ) { 2938 is->bv_len++; 2939 continue; 2940 } 2941 if ( is->bv_val[is->bv_len+1] == '"' ) { 2942 /* double dquote */ 2943 numdquotes++; 2944 is->bv_len+=2; 2945 continue; 2946 } 2947 break; 2948 } 2949 x.bv_val += is->bv_len+1; 2950 x.bv_len -= is->bv_len+1; 2951 2952 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber", 2953 STRLENOF("serialNumber")) == 0 )) 2954 { 2955 /* parse serialNumber */ 2956 int neg=0; 2957 x.bv_val += STRLENOF("serialNumber"); 2958 x.bv_len -= STRLENOF("serialNumber"); 2959 2960 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 2961 x.bv_val++; x.bv_len--; 2962 2963 /* eat leading spaces */ 2964 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) { 2965 /* empty */; 2966 } 2967 2968 sn->bv_val = x.bv_val; 2969 sn->bv_len = 0; 2970 2971 if( sn->bv_val[0] == '-' ) { 2972 neg++; 2973 sn->bv_len++; 2974 } 2975 2976 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || 2977 sn->bv_val[1] == 'X' )) { 2978 is_hex = 1; 2979 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2980 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2981 } 2982 } else if ( sn->bv_val[0] == '\'' ) { 2983 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2984 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; 2985 } 2986 if ( sn->bv_val[sn->bv_len] == '\'' && 2987 sn->bv_val[sn->bv_len+1] == 'H' ) 2988 is_hex = 1; 2989 else 2990 return LDAP_INVALID_SYNTAX; 2991 sn->bv_len += 2; 2992 } else { 2993 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { 2994 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; 2995 } 2996 } 2997 2998 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; 2999 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) { 3000 return LDAP_INVALID_SYNTAX; 3001 } 3002 3003 x.bv_val += sn->bv_len; 3004 x.bv_len -= sn->bv_len; 3005 3006 } else return LDAP_INVALID_SYNTAX; 3007 3008 /* eat trailing spaces */ 3009 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 3010 /* empty */; 3011 } 3012 3013 /* should have no characters left... */ 3014 if( x.bv_len ) return LDAP_INVALID_SYNTAX; 3015 3016 if ( numdquotes == 0 ) { 3017 ber_dupbv_x( &ni, is, ctx ); 3018 } else { 3019 ber_int_t src, dst; 3020 3021 ni.bv_len = is->bv_len - numdquotes; 3022 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 3023 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 3024 if ( is->bv_val[src] == '"' ) { 3025 src++; 3026 } 3027 ni.bv_val[dst] = is->bv_val[src]; 3028 } 3029 ni.bv_val[dst] = '\0'; 3030 } 3031 3032 *is = ni; 3033 } 3034 3035 return 0; 3036 } 3037 3038 static int 3039 serialNumberAndIssuerValidate( 3040 Syntax *syntax, 3041 struct berval *in ) 3042 { 3043 int rc; 3044 struct berval sn, i; 3045 3046 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n", 3047 in->bv_val, 0, 0 ); 3048 3049 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL ); 3050 if ( rc ) 3051 return rc; 3052 3053 /* validate DN -- doesn't handle double dquote */ 3054 rc = dnValidate( NULL, &i ); 3055 if( rc ) 3056 rc = LDAP_INVALID_SYNTAX; 3057 3058 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3059 slap_sl_free( i.bv_val, NULL ); 3060 } 3061 3062 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n", 3063 0, 0, 0 ); 3064 return rc; 3065 } 3066 3067 int 3068 serialNumberAndIssuerPretty( 3069 Syntax *syntax, 3070 struct berval *in, 3071 struct berval *out, 3072 void *ctx ) 3073 { 3074 int n, rc; 3075 struct berval sn, i, ni; 3076 3077 assert( in != NULL ); 3078 assert( out != NULL ); 3079 3080 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", 3081 in->bv_val, 0, 0 ); 3082 3083 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3084 if ( rc ) 3085 return rc; 3086 3087 rc = dnPretty( syntax, &i, &ni, ctx ); 3088 3089 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3090 slap_sl_free( i.bv_val, ctx ); 3091 } 3092 3093 if( rc ) return LDAP_INVALID_SYNTAX; 3094 3095 /* make room from sn + "$" */ 3096 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }") 3097 + sn.bv_len + ni.bv_len; 3098 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3099 3100 if( out->bv_val == NULL ) { 3101 out->bv_len = 0; 3102 slap_sl_free( ni.bv_val, ctx ); 3103 return LDAP_OTHER; 3104 } 3105 3106 n = 0; 3107 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", 3108 STRLENOF("{ serialNumber ")); 3109 n = STRLENOF("{ serialNumber "); 3110 3111 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); 3112 n += sn.bv_len; 3113 3114 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\"")); 3115 n += STRLENOF(", issuer rdnSequence:\""); 3116 3117 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); 3118 n += ni.bv_len; 3119 3120 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }")); 3121 n += STRLENOF("\" }"); 3122 3123 out->bv_val[n] = '\0'; 3124 3125 assert( n == out->bv_len ); 3126 3127 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n", 3128 out->bv_val, 0, 0 ); 3129 3130 slap_sl_free( ni.bv_val, ctx ); 3131 3132 return LDAP_SUCCESS; 3133 } 3134 3135 /* 3136 * This routine is called by certificateExactNormalize when 3137 * certificateExactNormalize receives a search string instead of 3138 * a certificate. This routine checks if the search value is valid 3139 * and then returns the normalized value 3140 */ 3141 static int 3142 serialNumberAndIssuerNormalize( 3143 slap_mask_t usage, 3144 Syntax *syntax, 3145 MatchingRule *mr, 3146 struct berval *in, 3147 struct berval *out, 3148 void *ctx ) 3149 { 3150 struct berval sn, sn2, i, ni; 3151 char sbuf[64], *stmp = sbuf; 3152 int rc; 3153 ber_len_t n; 3154 3155 assert( in != NULL ); 3156 assert( out != NULL ); 3157 3158 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", 3159 in->bv_val, 0, 0 ); 3160 3161 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3162 if ( rc ) 3163 return rc; 3164 3165 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 3166 3167 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3168 slap_sl_free( i.bv_val, ctx ); 3169 } 3170 3171 if( rc ) return LDAP_INVALID_SYNTAX; 3172 3173 /* Convert sn to canonical hex */ 3174 if ( sn.bv_len > sizeof( sbuf )) { 3175 stmp = slap_sl_malloc( sn.bv_len, ctx ); 3176 } 3177 sn2.bv_val = stmp; 3178 sn2.bv_len = sn.bv_len; 3179 if ( lutil_str2bin( &sn, &sn2, ctx )) { 3180 rc = LDAP_INVALID_SYNTAX; 3181 goto func_leave; 3182 } 3183 3184 /* make room for sn + "$" */ 3185 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3186 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len; 3187 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3188 3189 if( out->bv_val == NULL ) { 3190 out->bv_len = 0; 3191 slap_sl_free( ni.bv_val, ctx ); 3192 rc = LDAP_OTHER; 3193 goto func_leave; 3194 } 3195 3196 n = 0; 3197 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", 3198 STRLENOF( "{ serialNumber " )); 3199 n = STRLENOF( "{ serialNumber " ); 3200 3201 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); 3202 { 3203 int j; 3204 unsigned char *v = (unsigned char *)sn2.bv_val; 3205 out->bv_val[n++] = '\''; 3206 for ( j = 0; j < sn2.bv_len; j++ ) { 3207 snprintf( &out->bv_val[n], out->bv_len - n + 1, 3208 "%02X", v[j] ); 3209 n += 2; 3210 } 3211 out->bv_val[n++] = '\''; 3212 out->bv_val[n++] = 'H'; 3213 } 3214 3215 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); 3216 n += STRLENOF( ", issuer rdnSequence:\"" ); 3217 3218 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); 3219 n += ni.bv_len; 3220 3221 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" )); 3222 n += STRLENOF( "\" }" ); 3223 3224 out->bv_val[n] = '\0'; 3225 3226 assert( n == out->bv_len ); 3227 3228 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n", 3229 out->bv_val, 0, 0 ); 3230 3231 func_leave: 3232 if ( stmp != sbuf ) 3233 slap_sl_free( stmp, ctx ); 3234 slap_sl_free( ni.bv_val, ctx ); 3235 3236 return rc; 3237 } 3238 3239 static int 3240 certificateExactNormalize( 3241 slap_mask_t usage, 3242 Syntax *syntax, 3243 MatchingRule *mr, 3244 struct berval *val, 3245 struct berval *normalized, 3246 void *ctx ) 3247 { 3248 BerElementBuffer berbuf; 3249 BerElement *ber = (BerElement *)&berbuf; 3250 ber_tag_t tag; 3251 ber_len_t len; 3252 ber_int_t i; 3253 char serialbuf[64], *serial = serialbuf; 3254 ber_len_t seriallen; 3255 struct berval issuer_dn = BER_BVNULL, bvdn; 3256 unsigned char *p; 3257 int rc = LDAP_INVALID_SYNTAX; 3258 3259 if( BER_BVISEMPTY( val ) ) goto done; 3260 3261 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3262 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx); 3263 } 3264 3265 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3266 3267 ber_init2( ber, val, LBER_USE_DER ); 3268 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 3269 tag = ber_skip_tag( ber, &len ); /* Sequence */ 3270 tag = ber_peek_tag( ber, &len ); /* Optional version? */ 3271 if ( tag == SLAP_X509_OPT_C_VERSION ) { 3272 tag = ber_skip_tag( ber, &len ); 3273 tag = ber_get_int( ber, &i ); /* version */ 3274 } 3275 3276 /* NOTE: move the test here from certificateValidate, 3277 * so that we can validate certs with serial longer 3278 * than sizeof(ber_int_t) */ 3279 tag = ber_peek_tag( ber, &len ); /* serial */ 3280 3281 /* Use hex format. '123456789abcdef'H 3282 */ 3283 { 3284 unsigned char *ptr; 3285 char *sptr; 3286 3287 tag = ber_skip_tag( ber, &len ); 3288 ptr = (unsigned char *)ber->ber_ptr; 3289 ber_skip_data( ber, len ); 3290 3291 /* Check for minimal encodings */ 3292 if ( len > 1 ) { 3293 if ( ptr[0] & 0x80 ) { 3294 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 )) 3295 return LDAP_INVALID_SYNTAX; 3296 } else if ( ptr[0] == 0 ) { 3297 if (!( ptr[1] & 0x80 )) 3298 return LDAP_INVALID_SYNTAX; 3299 } 3300 } 3301 3302 seriallen = len * 2 + 4; /* quotes, H, NUL */ 3303 if ( seriallen > sizeof( serialbuf )) 3304 serial = slap_sl_malloc( seriallen, ctx ); 3305 sptr = serial; 3306 *sptr++ = '\''; 3307 for ( i = 0; i<len; i++ ) { 3308 sprintf( sptr, "%02X", ptr[i] ); 3309 sptr += 2; 3310 } 3311 *sptr++ = '\''; 3312 *sptr++ = 'H'; 3313 seriallen--; 3314 } 3315 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */ 3316 ber_skip_data( ber, len ); 3317 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 3318 len = ber_ptrlen( ber ); 3319 bvdn.bv_val = val->bv_val + len; 3320 bvdn.bv_len = val->bv_len - len; 3321 3322 rc = dnX509normalize( &bvdn, &issuer_dn ); 3323 if( rc != LDAP_SUCCESS ) goto done; 3324 3325 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3326 + seriallen + issuer_dn.bv_len; 3327 normalized->bv_val = ch_malloc(normalized->bv_len+1); 3328 3329 p = (unsigned char *)normalized->bv_val; 3330 3331 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " )); 3332 p += STRLENOF( "{ serialNumber " ); 3333 3334 AC_MEMCPY(p, serial, seriallen); 3335 p += seriallen; 3336 3337 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); 3338 p += STRLENOF( ", issuer rdnSequence:\"" ); 3339 3340 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); 3341 p += issuer_dn.bv_len; 3342 3343 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" )); 3344 p += STRLENOF( "\" }" ); 3345 3346 *p = '\0'; 3347 3348 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n", 3349 normalized->bv_val, NULL, NULL ); 3350 3351 rc = LDAP_SUCCESS; 3352 3353 done: 3354 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 3355 if ( serial != serialbuf ) ber_memfree_x( serial, ctx ); 3356 3357 return rc; 3358 } 3359 3360 static int 3361 hexValidate( 3362 Syntax *syntax, 3363 struct berval *in ) 3364 { 3365 int i; 3366 3367 assert( in != NULL ); 3368 assert( !BER_BVISNULL( in ) ); 3369 3370 for ( i = 0; i < in->bv_len; i++ ) { 3371 if ( !ASCII_HEX( in->bv_val[ i ] ) ) { 3372 return LDAP_INVALID_SYNTAX; 3373 } 3374 } 3375 3376 return LDAP_SUCCESS; 3377 } 3378 3379 /* Normalize a SID as used inside a CSN: 3380 * three-digit numeric string */ 3381 static int 3382 hexNormalize( 3383 slap_mask_t usage, 3384 Syntax *syntax, 3385 MatchingRule *mr, 3386 struct berval *val, 3387 struct berval *normalized, 3388 void *ctx ) 3389 { 3390 int i; 3391 3392 assert( val != NULL ); 3393 assert( normalized != NULL ); 3394 3395 ber_dupbv_x( normalized, val, ctx ); 3396 3397 for ( i = 0; i < normalized->bv_len; i++ ) { 3398 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) { 3399 ber_memfree_x( normalized->bv_val, ctx ); 3400 BER_BVZERO( normalized ); 3401 return LDAP_INVALID_SYNTAX; 3402 } 3403 3404 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 3405 } 3406 3407 return LDAP_SUCCESS; 3408 } 3409 3410 static int 3411 sidValidate ( 3412 Syntax *syntax, 3413 struct berval *in ) 3414 { 3415 assert( in != NULL ); 3416 assert( !BER_BVISNULL( in ) ); 3417 3418 if ( in->bv_len != 3 ) { 3419 return LDAP_INVALID_SYNTAX; 3420 } 3421 3422 return hexValidate( NULL, in ); 3423 } 3424 3425 /* Normalize a SID as used inside a CSN: 3426 * three-digit numeric string */ 3427 static int 3428 sidNormalize( 3429 slap_mask_t usage, 3430 Syntax *syntax, 3431 MatchingRule *mr, 3432 struct berval *val, 3433 struct berval *normalized, 3434 void *ctx ) 3435 { 3436 if ( val->bv_len != 3 ) { 3437 return LDAP_INVALID_SYNTAX; 3438 } 3439 3440 return hexNormalize( 0, NULL, NULL, val, normalized, ctx ); 3441 } 3442 3443 static int 3444 sidPretty( 3445 Syntax *syntax, 3446 struct berval *val, 3447 struct berval *out, 3448 void *ctx ) 3449 { 3450 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 3451 } 3452 3453 /* Normalize a SID as used inside a CSN, either as-is 3454 * (assertion value) or extracted from the CSN 3455 * (attribute value) */ 3456 static int 3457 csnSidNormalize( 3458 slap_mask_t usage, 3459 Syntax *syntax, 3460 MatchingRule *mr, 3461 struct berval *val, 3462 struct berval *normalized, 3463 void *ctx ) 3464 { 3465 struct berval bv; 3466 char *ptr, 3467 buf[ 4 ]; 3468 3469 3470 if ( BER_BVISEMPTY( val ) ) { 3471 return LDAP_INVALID_SYNTAX; 3472 } 3473 3474 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3475 return sidNormalize( 0, NULL, NULL, val, normalized, ctx ); 3476 } 3477 3478 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3479 3480 ptr = ber_bvchr( val, '#' ); 3481 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3482 return LDAP_INVALID_SYNTAX; 3483 } 3484 3485 bv.bv_val = ptr + 1; 3486 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 3487 3488 ptr = ber_bvchr( &bv, '#' ); 3489 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3490 return LDAP_INVALID_SYNTAX; 3491 } 3492 3493 bv.bv_val = ptr + 1; 3494 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 3495 3496 ptr = ber_bvchr( &bv, '#' ); 3497 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3498 return LDAP_INVALID_SYNTAX; 3499 } 3500 3501 bv.bv_len = ptr - bv.bv_val; 3502 3503 if ( bv.bv_len == 2 ) { 3504 /* OpenLDAP 2.3 SID */ 3505 buf[ 0 ] = '0'; 3506 buf[ 1 ] = bv.bv_val[ 0 ]; 3507 buf[ 2 ] = bv.bv_val[ 1 ]; 3508 buf[ 3 ] = '\0'; 3509 3510 bv.bv_val = buf; 3511 bv.bv_len = 3; 3512 } 3513 3514 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx ); 3515 } 3516 3517 static int 3518 csnValidate( 3519 Syntax *syntax, 3520 struct berval *in ) 3521 { 3522 struct berval bv; 3523 char *ptr; 3524 int rc; 3525 3526 assert( in != NULL ); 3527 assert( !BER_BVISNULL( in ) ); 3528 3529 if ( BER_BVISEMPTY( in ) ) { 3530 return LDAP_INVALID_SYNTAX; 3531 } 3532 3533 bv = *in; 3534 3535 ptr = ber_bvchr( &bv, '#' ); 3536 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) { 3537 return LDAP_INVALID_SYNTAX; 3538 } 3539 3540 bv.bv_len = ptr - bv.bv_val; 3541 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) && 3542 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) 3543 { 3544 return LDAP_INVALID_SYNTAX; 3545 } 3546 3547 rc = generalizedTimeValidate( NULL, &bv ); 3548 if ( rc != LDAP_SUCCESS ) { 3549 return rc; 3550 } 3551 3552 bv.bv_val = ptr + 1; 3553 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3554 3555 ptr = ber_bvchr( &bv, '#' ); 3556 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { 3557 return LDAP_INVALID_SYNTAX; 3558 } 3559 3560 bv.bv_len = ptr - bv.bv_val; 3561 if ( bv.bv_len != 6 ) { 3562 return LDAP_INVALID_SYNTAX; 3563 } 3564 3565 rc = hexValidate( NULL, &bv ); 3566 if ( rc != LDAP_SUCCESS ) { 3567 return rc; 3568 } 3569 3570 bv.bv_val = ptr + 1; 3571 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3572 3573 ptr = ber_bvchr( &bv, '#' ); 3574 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { 3575 return LDAP_INVALID_SYNTAX; 3576 } 3577 3578 bv.bv_len = ptr - bv.bv_val; 3579 if ( bv.bv_len == 2 ) { 3580 /* tolerate old 2-digit replica-id */ 3581 rc = hexValidate( NULL, &bv ); 3582 3583 } else { 3584 rc = sidValidate( NULL, &bv ); 3585 } 3586 if ( rc != LDAP_SUCCESS ) { 3587 return rc; 3588 } 3589 3590 bv.bv_val = ptr + 1; 3591 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 3592 3593 if ( bv.bv_len != 6 ) { 3594 return LDAP_INVALID_SYNTAX; 3595 } 3596 3597 return hexValidate( NULL, &bv ); 3598 } 3599 3600 /* Normalize a CSN in OpenLDAP 2.1 format */ 3601 static int 3602 csnNormalize21( 3603 slap_mask_t usage, 3604 Syntax *syntax, 3605 MatchingRule *mr, 3606 struct berval *val, 3607 struct berval *normalized, 3608 void *ctx ) 3609 { 3610 struct berval gt, cnt, sid, mod; 3611 struct berval bv; 3612 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 3613 char *ptr; 3614 int i; 3615 3616 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3617 assert( !BER_BVISEMPTY( val ) ); 3618 3619 gt = *val; 3620 3621 ptr = ber_bvchr( >, '#' ); 3622 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) { 3623 return LDAP_INVALID_SYNTAX; 3624 } 3625 3626 gt.bv_len = ptr - gt.bv_val; 3627 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) { 3628 return LDAP_INVALID_SYNTAX; 3629 } 3630 3631 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) { 3632 return LDAP_INVALID_SYNTAX; 3633 } 3634 3635 cnt.bv_val = ptr + 1; 3636 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3637 3638 ptr = ber_bvchr( &cnt, '#' ); 3639 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3640 return LDAP_INVALID_SYNTAX; 3641 } 3642 3643 cnt.bv_len = ptr - cnt.bv_val; 3644 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) { 3645 return LDAP_INVALID_SYNTAX; 3646 } 3647 3648 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) { 3649 return LDAP_INVALID_SYNTAX; 3650 } 3651 3652 cnt.bv_val += STRLENOF( "0x" ); 3653 cnt.bv_len -= STRLENOF( "0x" ); 3654 3655 sid.bv_val = ptr + 1; 3656 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3657 3658 ptr = ber_bvchr( &sid, '#' ); 3659 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3660 return LDAP_INVALID_SYNTAX; 3661 } 3662 3663 sid.bv_len = ptr - sid.bv_val; 3664 if ( sid.bv_len != STRLENOF( "0" ) ) { 3665 return LDAP_INVALID_SYNTAX; 3666 } 3667 3668 mod.bv_val = ptr + 1; 3669 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3670 if ( mod.bv_len != STRLENOF( "0000" ) ) { 3671 return LDAP_INVALID_SYNTAX; 3672 } 3673 3674 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 3675 bv.bv_val = buf; 3676 3677 ptr = bv.bv_val; 3678 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) ); 3679 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ], 3680 STRLENOF( "MM" ) ); 3681 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ], 3682 STRLENOF( "SS" ) ); 3683 ptr = lutil_strcopy( ptr, ".000000Z#00" ); 3684 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len ); 3685 *ptr++ = '#'; 3686 *ptr++ = '0'; 3687 *ptr++ = '0'; 3688 *ptr++ = sid.bv_val[ 0 ]; 3689 *ptr++ = '#'; 3690 *ptr++ = '0'; 3691 *ptr++ = '0'; 3692 for ( i = 0; i < mod.bv_len; i++ ) { 3693 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 3694 } 3695 *ptr = '\0'; 3696 3697 assert( ptr - bv.bv_val == bv.bv_len ); 3698 3699 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 3700 return LDAP_INVALID_SYNTAX; 3701 } 3702 3703 ber_dupbv_x( normalized, &bv, ctx ); 3704 3705 return LDAP_SUCCESS; 3706 } 3707 3708 /* Normalize a CSN in OpenLDAP 2.3 format */ 3709 static int 3710 csnNormalize23( 3711 slap_mask_t usage, 3712 Syntax *syntax, 3713 MatchingRule *mr, 3714 struct berval *val, 3715 struct berval *normalized, 3716 void *ctx ) 3717 { 3718 struct berval gt, cnt, sid, mod; 3719 struct berval bv; 3720 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 3721 char *ptr; 3722 int i; 3723 3724 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3725 assert( !BER_BVISEMPTY( val ) ); 3726 3727 gt = *val; 3728 3729 ptr = ber_bvchr( >, '#' ); 3730 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) { 3731 return LDAP_INVALID_SYNTAX; 3732 } 3733 3734 gt.bv_len = ptr - gt.bv_val; 3735 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 3736 return LDAP_INVALID_SYNTAX; 3737 } 3738 3739 cnt.bv_val = ptr + 1; 3740 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3741 3742 ptr = ber_bvchr( &cnt, '#' ); 3743 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3744 return LDAP_INVALID_SYNTAX; 3745 } 3746 3747 cnt.bv_len = ptr - cnt.bv_val; 3748 if ( cnt.bv_len != STRLENOF( "000000" ) ) { 3749 return LDAP_INVALID_SYNTAX; 3750 } 3751 3752 sid.bv_val = ptr + 1; 3753 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3754 3755 ptr = ber_bvchr( &sid, '#' ); 3756 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3757 return LDAP_INVALID_SYNTAX; 3758 } 3759 3760 sid.bv_len = ptr - sid.bv_val; 3761 if ( sid.bv_len != STRLENOF( "00" ) ) { 3762 return LDAP_INVALID_SYNTAX; 3763 } 3764 3765 mod.bv_val = ptr + 1; 3766 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3767 if ( mod.bv_len != STRLENOF( "000000" ) ) { 3768 return LDAP_INVALID_SYNTAX; 3769 } 3770 3771 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 3772 bv.bv_val = buf; 3773 3774 ptr = bv.bv_val; 3775 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 ); 3776 ptr = lutil_strcopy( ptr, ".000000Z#" ); 3777 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len ); 3778 *ptr++ = '#'; 3779 *ptr++ = '0'; 3780 for ( i = 0; i < sid.bv_len; i++ ) { 3781 *ptr++ = TOLOWER( sid.bv_val[ i ] ); 3782 } 3783 *ptr++ = '#'; 3784 for ( i = 0; i < mod.bv_len; i++ ) { 3785 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 3786 } 3787 *ptr = '\0'; 3788 3789 assert( ptr - bv.bv_val == bv.bv_len ); 3790 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 3791 return LDAP_INVALID_SYNTAX; 3792 } 3793 3794 ber_dupbv_x( normalized, &bv, ctx ); 3795 3796 return LDAP_SUCCESS; 3797 } 3798 3799 /* Normalize a CSN */ 3800 static int 3801 csnNormalize( 3802 slap_mask_t usage, 3803 Syntax *syntax, 3804 MatchingRule *mr, 3805 struct berval *val, 3806 struct berval *normalized, 3807 void *ctx ) 3808 { 3809 struct berval cnt, sid, mod; 3810 char *ptr; 3811 int i; 3812 3813 assert( val != NULL ); 3814 assert( normalized != NULL ); 3815 3816 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 3817 3818 if ( BER_BVISEMPTY( val ) ) { 3819 return LDAP_INVALID_SYNTAX; 3820 } 3821 3822 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) { 3823 /* Openldap <= 2.3 */ 3824 3825 return csnNormalize23( usage, syntax, mr, val, normalized, ctx ); 3826 } 3827 3828 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) { 3829 /* Openldap 2.1 */ 3830 3831 return csnNormalize21( usage, syntax, mr, val, normalized, ctx ); 3832 } 3833 3834 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) { 3835 return LDAP_INVALID_SYNTAX; 3836 } 3837 3838 ptr = ber_bvchr( val, '#' ); 3839 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3840 return LDAP_INVALID_SYNTAX; 3841 } 3842 3843 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) { 3844 return LDAP_INVALID_SYNTAX; 3845 } 3846 3847 cnt.bv_val = ptr + 1; 3848 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 3849 3850 ptr = ber_bvchr( &cnt, '#' ); 3851 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3852 return LDAP_INVALID_SYNTAX; 3853 } 3854 3855 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) { 3856 return LDAP_INVALID_SYNTAX; 3857 } 3858 3859 sid.bv_val = ptr + 1; 3860 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 3861 3862 ptr = ber_bvchr( &sid, '#' ); 3863 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { 3864 return LDAP_INVALID_SYNTAX; 3865 } 3866 3867 sid.bv_len = ptr - sid.bv_val; 3868 if ( sid.bv_len != STRLENOF( "000" ) ) { 3869 return LDAP_INVALID_SYNTAX; 3870 } 3871 3872 mod.bv_val = ptr + 1; 3873 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 3874 3875 if ( mod.bv_len != STRLENOF( "000000" ) ) { 3876 return LDAP_INVALID_SYNTAX; 3877 } 3878 3879 ber_dupbv_x( normalized, val, ctx ); 3880 3881 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" ); 3882 i < normalized->bv_len; i++ ) 3883 { 3884 /* assume it's already validated that's all hex digits */ 3885 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 3886 } 3887 3888 return LDAP_SUCCESS; 3889 } 3890 3891 static int 3892 csnPretty( 3893 Syntax *syntax, 3894 struct berval *val, 3895 struct berval *out, 3896 void *ctx ) 3897 { 3898 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 3899 } 3900 3901 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX 3902 /* slight optimization - does not need the start parameter */ 3903 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f) 3904 enum { start = 0 }; 3905 #endif 3906 3907 static int 3908 check_time_syntax (struct berval *val, 3909 int start, 3910 int *parts, 3911 struct berval *fraction) 3912 { 3913 /* 3914 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) 3915 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM] 3916 * GeneralizedTime supports leap seconds, UTCTime does not. 3917 */ 3918 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 }; 3919 static const int mdays[2][12] = { 3920 /* non-leap years */ 3921 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 3922 /* leap years */ 3923 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 3924 }; 3925 char *p, *e; 3926 int part, c, c1, c2, tzoffset, leapyear = 0; 3927 3928 p = val->bv_val; 3929 e = p + val->bv_len; 3930 3931 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 3932 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */ 3933 #endif 3934 for (part = start; part < 7 && p < e; part++) { 3935 c1 = *p; 3936 if (!ASCII_DIGIT(c1)) { 3937 break; 3938 } 3939 p++; 3940 if (p == e) { 3941 return LDAP_INVALID_SYNTAX; 3942 } 3943 c = *p++; 3944 if (!ASCII_DIGIT(c)) { 3945 return LDAP_INVALID_SYNTAX; 3946 } 3947 c += c1 * 10 - '0' * 11; 3948 if ((part | 1) == 3) { 3949 --c; 3950 if (c < 0) { 3951 return LDAP_INVALID_SYNTAX; 3952 } 3953 } 3954 if (c >= ceiling[part]) { 3955 if (! (c == 60 && part == 6 && start == 0)) 3956 return LDAP_INVALID_SYNTAX; 3957 } 3958 parts[part] = c; 3959 } 3960 if (part < 5 + start) { 3961 return LDAP_INVALID_SYNTAX; 3962 } 3963 for (; part < 9; part++) { 3964 parts[part] = 0; 3965 } 3966 3967 /* leapyear check for the Gregorian calendar (year>1581) */ 3968 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) { 3969 leapyear = 1; 3970 } 3971 3972 if (parts[3] >= mdays[leapyear][parts[2]]) { 3973 return LDAP_INVALID_SYNTAX; 3974 } 3975 3976 if (start == 0) { 3977 fraction->bv_val = p; 3978 fraction->bv_len = 0; 3979 if (p < e && (*p == '.' || *p == ',')) { 3980 char *end_num; 3981 while (++p < e && ASCII_DIGIT(*p)) { 3982 /* EMTPY */; 3983 } 3984 if (p - fraction->bv_val == 1) { 3985 return LDAP_INVALID_SYNTAX; 3986 } 3987 for (end_num = p; end_num[-1] == '0'; --end_num) { 3988 /* EMPTY */; 3989 } 3990 c = end_num - fraction->bv_val; 3991 if (c != 1) fraction->bv_len = c; 3992 } 3993 } 3994 3995 if (p == e) { 3996 /* no time zone */ 3997 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 3998 } 3999 4000 tzoffset = *p++; 4001 switch (tzoffset) { 4002 default: 4003 return LDAP_INVALID_SYNTAX; 4004 case 'Z': 4005 /* UTC */ 4006 break; 4007 case '+': 4008 case '-': 4009 for (part = 7; part < 9 && p < e; part++) { 4010 c1 = *p; 4011 if (!ASCII_DIGIT(c1)) { 4012 break; 4013 } 4014 p++; 4015 if (p == e) { 4016 return LDAP_INVALID_SYNTAX; 4017 } 4018 c2 = *p++; 4019 if (!ASCII_DIGIT(c2)) { 4020 return LDAP_INVALID_SYNTAX; 4021 } 4022 parts[part] = c1 * 10 + c2 - '0' * 11; 4023 if (parts[part] >= ceiling[part]) { 4024 return LDAP_INVALID_SYNTAX; 4025 } 4026 } 4027 if (part < 8 + start) { 4028 return LDAP_INVALID_SYNTAX; 4029 } 4030 4031 if (tzoffset == '-') { 4032 /* negative offset to UTC, ie west of Greenwich */ 4033 parts[4] += parts[7]; 4034 parts[5] += parts[8]; 4035 /* offset is just hhmm, no seconds */ 4036 for (part = 6; --part >= 0; ) { 4037 if (part != 3) { 4038 c = ceiling[part]; 4039 } else { 4040 c = mdays[leapyear][parts[2]]; 4041 } 4042 if (parts[part] >= c) { 4043 if (part == 0) { 4044 return LDAP_INVALID_SYNTAX; 4045 } 4046 parts[part] -= c; 4047 parts[part - 1]++; 4048 continue; 4049 } else if (part != 5) { 4050 break; 4051 } 4052 } 4053 } else { 4054 /* positive offset to UTC, ie east of Greenwich */ 4055 parts[4] -= parts[7]; 4056 parts[5] -= parts[8]; 4057 for (part = 6; --part >= 0; ) { 4058 if (parts[part] < 0) { 4059 if (part == 0) { 4060 return LDAP_INVALID_SYNTAX; 4061 } 4062 if (part != 3) { 4063 c = ceiling[part]; 4064 } else { 4065 /* make first arg to % non-negative */ 4066 c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; 4067 } 4068 parts[part] += c; 4069 parts[part - 1]--; 4070 continue; 4071 } else if (part != 5) { 4072 break; 4073 } 4074 } 4075 } 4076 } 4077 4078 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 4079 } 4080 4081 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 4082 4083 #if 0 4084 static int 4085 xutcTimeNormalize( 4086 Syntax *syntax, 4087 struct berval *val, 4088 struct berval *normalized ) 4089 { 4090 int parts[9], rc; 4091 4092 rc = check_time_syntax(val, 1, parts, NULL); 4093 if (rc != LDAP_SUCCESS) { 4094 return rc; 4095 } 4096 4097 normalized->bv_val = ch_malloc( 14 ); 4098 if ( normalized->bv_val == NULL ) { 4099 return LBER_ERROR_MEMORY; 4100 } 4101 4102 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ", 4103 parts[1], parts[2] + 1, parts[3] + 1, 4104 parts[4], parts[5], parts[6] ); 4105 normalized->bv_len = 13; 4106 4107 return LDAP_SUCCESS; 4108 } 4109 #endif /* 0 */ 4110 4111 static int 4112 utcTimeValidate( 4113 Syntax *syntax, 4114 struct berval *in ) 4115 { 4116 int parts[9]; 4117 return check_time_syntax(in, 1, parts, NULL); 4118 } 4119 4120 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ 4121 4122 static int 4123 generalizedTimeValidate( 4124 Syntax *syntax, 4125 struct berval *in ) 4126 { 4127 int parts[9]; 4128 struct berval fraction; 4129 return check_time_syntax(in, 0, parts, &fraction); 4130 } 4131 4132 static int 4133 generalizedTimeNormalize( 4134 slap_mask_t usage, 4135 Syntax *syntax, 4136 MatchingRule *mr, 4137 struct berval *val, 4138 struct berval *normalized, 4139 void *ctx ) 4140 { 4141 int parts[9], rc; 4142 unsigned int len; 4143 struct berval fraction; 4144 4145 rc = check_time_syntax(val, 0, parts, &fraction); 4146 if (rc != LDAP_SUCCESS) { 4147 return rc; 4148 } 4149 4150 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len; 4151 normalized->bv_val = slap_sl_malloc( len + 1, ctx ); 4152 if ( BER_BVISNULL( normalized ) ) { 4153 return LBER_ERROR_MEMORY; 4154 } 4155 4156 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d", 4157 parts[0], parts[1], parts[2] + 1, parts[3] + 1, 4158 parts[4], parts[5], parts[6] ); 4159 if ( !BER_BVISEMPTY( &fraction ) ) { 4160 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1, 4161 fraction.bv_val, fraction.bv_len ); 4162 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.'; 4163 } 4164 strcpy( normalized->bv_val + len-1, "Z" ); 4165 normalized->bv_len = len; 4166 4167 return LDAP_SUCCESS; 4168 } 4169 4170 static int 4171 generalizedTimeOrderingMatch( 4172 int *matchp, 4173 slap_mask_t flags, 4174 Syntax *syntax, 4175 MatchingRule *mr, 4176 struct berval *value, 4177 void *assertedValue ) 4178 { 4179 struct berval *asserted = (struct berval *) assertedValue; 4180 ber_len_t v_len = value->bv_len; 4181 ber_len_t av_len = asserted->bv_len; 4182 4183 /* ignore trailing 'Z' when comparing */ 4184 int match = memcmp( value->bv_val, asserted->bv_val, 4185 (v_len < av_len ? v_len : av_len) - 1 ); 4186 if ( match == 0 ) match = v_len - av_len; 4187 4188 *matchp = match; 4189 return LDAP_SUCCESS; 4190 } 4191 4192 /* Index generation function */ 4193 int generalizedTimeIndexer( 4194 slap_mask_t use, 4195 slap_mask_t flags, 4196 Syntax *syntax, 4197 MatchingRule *mr, 4198 struct berval *prefix, 4199 BerVarray values, 4200 BerVarray *keysp, 4201 void *ctx ) 4202 { 4203 int i, j; 4204 BerVarray keys; 4205 char tmp[5]; 4206 BerValue bvtmp; /* 40 bit index */ 4207 struct lutil_tm tm; 4208 struct lutil_timet tt; 4209 4210 bvtmp.bv_len = sizeof(tmp); 4211 bvtmp.bv_val = tmp; 4212 for( i=0; values[i].bv_val != NULL; i++ ) { 4213 /* just count them */ 4214 } 4215 4216 /* we should have at least one value at this point */ 4217 assert( i > 0 ); 4218 4219 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 4220 4221 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 4222 for( i=0, j=0; values[i].bv_val != NULL; i++ ) { 4223 assert(values[i].bv_val != NULL && values[i].bv_len >= 10); 4224 /* Use 40 bits of time for key */ 4225 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) { 4226 lutil_tm2time( &tm, &tt ); 4227 tmp[0] = tt.tt_gsec & 0xff; 4228 tmp[4] = tt.tt_sec & 0xff; 4229 tt.tt_sec >>= 8; 4230 tmp[3] = tt.tt_sec & 0xff; 4231 tt.tt_sec >>= 8; 4232 tmp[2] = tt.tt_sec & 0xff; 4233 tt.tt_sec >>= 8; 4234 tmp[1] = tt.tt_sec & 0xff; 4235 4236 ber_dupbv_x(&keys[j++], &bvtmp, ctx ); 4237 } 4238 } 4239 4240 keys[j].bv_val = NULL; 4241 keys[j].bv_len = 0; 4242 4243 *keysp = keys; 4244 4245 return LDAP_SUCCESS; 4246 } 4247 4248 /* Index generation function */ 4249 int generalizedTimeFilter( 4250 slap_mask_t use, 4251 slap_mask_t flags, 4252 Syntax *syntax, 4253 MatchingRule *mr, 4254 struct berval *prefix, 4255 void * assertedValue, 4256 BerVarray *keysp, 4257 void *ctx ) 4258 { 4259 BerVarray keys; 4260 char tmp[5]; 4261 BerValue bvtmp; /* 40 bit index */ 4262 BerValue *value = (BerValue *) assertedValue; 4263 struct lutil_tm tm; 4264 struct lutil_timet tt; 4265 4266 bvtmp.bv_len = sizeof(tmp); 4267 bvtmp.bv_val = tmp; 4268 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 4269 /* Use 40 bits of time for key */ 4270 if ( value->bv_val && value->bv_len >= 10 && 4271 lutil_parsetime( value->bv_val, &tm ) == 0 ) { 4272 4273 lutil_tm2time( &tm, &tt ); 4274 tmp[0] = tt.tt_gsec & 0xff; 4275 tmp[4] = tt.tt_sec & 0xff; 4276 tt.tt_sec >>= 8; 4277 tmp[3] = tt.tt_sec & 0xff; 4278 tt.tt_sec >>= 8; 4279 tmp[2] = tt.tt_sec & 0xff; 4280 tt.tt_sec >>= 8; 4281 tmp[1] = tt.tt_sec & 0xff; 4282 4283 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 4284 ber_dupbv_x(keys, &bvtmp, ctx ); 4285 keys[1].bv_val = NULL; 4286 keys[1].bv_len = 0; 4287 } else { 4288 keys = NULL; 4289 } 4290 4291 *keysp = keys; 4292 4293 return LDAP_SUCCESS; 4294 } 4295 4296 static int 4297 deliveryMethodValidate( 4298 Syntax *syntax, 4299 struct berval *val ) 4300 { 4301 #undef LENOF 4302 #define LENOF(s) (sizeof(s)-1) 4303 struct berval tmp = *val; 4304 /* 4305 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod ) 4306 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" / 4307 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone" 4308 */ 4309 again: 4310 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4311 4312 switch( tmp.bv_val[0] ) { 4313 case 'a': 4314 case 'A': 4315 if(( tmp.bv_len >= LENOF("any") ) && 4316 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 )) 4317 { 4318 tmp.bv_len -= LENOF("any"); 4319 tmp.bv_val += LENOF("any"); 4320 break; 4321 } 4322 return LDAP_INVALID_SYNTAX; 4323 4324 case 'm': 4325 case 'M': 4326 if(( tmp.bv_len >= LENOF("mhs") ) && 4327 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 )) 4328 { 4329 tmp.bv_len -= LENOF("mhs"); 4330 tmp.bv_val += LENOF("mhs"); 4331 break; 4332 } 4333 return LDAP_INVALID_SYNTAX; 4334 4335 case 'p': 4336 case 'P': 4337 if(( tmp.bv_len >= LENOF("physical") ) && 4338 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 )) 4339 { 4340 tmp.bv_len -= LENOF("physical"); 4341 tmp.bv_val += LENOF("physical"); 4342 break; 4343 } 4344 return LDAP_INVALID_SYNTAX; 4345 4346 case 't': 4347 case 'T': /* telex or teletex or telephone */ 4348 if(( tmp.bv_len >= LENOF("telex") ) && 4349 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 )) 4350 { 4351 tmp.bv_len -= LENOF("telex"); 4352 tmp.bv_val += LENOF("telex"); 4353 break; 4354 } 4355 if(( tmp.bv_len >= LENOF("teletex") ) && 4356 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 )) 4357 { 4358 tmp.bv_len -= LENOF("teletex"); 4359 tmp.bv_val += LENOF("teletex"); 4360 break; 4361 } 4362 if(( tmp.bv_len >= LENOF("telephone") ) && 4363 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 )) 4364 { 4365 tmp.bv_len -= LENOF("telephone"); 4366 tmp.bv_val += LENOF("telephone"); 4367 break; 4368 } 4369 return LDAP_INVALID_SYNTAX; 4370 4371 case 'g': 4372 case 'G': /* g3fax or g4fax */ 4373 if(( tmp.bv_len >= LENOF("g3fax") ) && ( 4374 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) || 4375 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 ))) 4376 { 4377 tmp.bv_len -= LENOF("g3fax"); 4378 tmp.bv_val += LENOF("g3fax"); 4379 break; 4380 } 4381 return LDAP_INVALID_SYNTAX; 4382 4383 case 'i': 4384 case 'I': 4385 if(( tmp.bv_len >= LENOF("ia5") ) && 4386 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 )) 4387 { 4388 tmp.bv_len -= LENOF("ia5"); 4389 tmp.bv_val += LENOF("ia5"); 4390 break; 4391 } 4392 return LDAP_INVALID_SYNTAX; 4393 4394 case 'v': 4395 case 'V': 4396 if(( tmp.bv_len >= LENOF("videotex") ) && 4397 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 )) 4398 { 4399 tmp.bv_len -= LENOF("videotex"); 4400 tmp.bv_val += LENOF("videotex"); 4401 break; 4402 } 4403 return LDAP_INVALID_SYNTAX; 4404 4405 default: 4406 return LDAP_INVALID_SYNTAX; 4407 } 4408 4409 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS; 4410 4411 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 4412 tmp.bv_len++; 4413 tmp.bv_val--; 4414 } 4415 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) { 4416 tmp.bv_len++; 4417 tmp.bv_val--; 4418 } else { 4419 return LDAP_INVALID_SYNTAX; 4420 } 4421 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 4422 tmp.bv_len++; 4423 tmp.bv_val--; 4424 } 4425 4426 goto again; 4427 } 4428 4429 static int 4430 nisNetgroupTripleValidate( 4431 Syntax *syntax, 4432 struct berval *val ) 4433 { 4434 char *p, *e; 4435 int commas = 0; 4436 4437 if ( BER_BVISEMPTY( val ) ) { 4438 return LDAP_INVALID_SYNTAX; 4439 } 4440 4441 p = (char *)val->bv_val; 4442 e = p + val->bv_len; 4443 4444 if ( *p != '(' /*')'*/ ) { 4445 return LDAP_INVALID_SYNTAX; 4446 } 4447 4448 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) { 4449 if ( *p == ',' ) { 4450 commas++; 4451 if ( commas > 2 ) { 4452 return LDAP_INVALID_SYNTAX; 4453 } 4454 4455 } else if ( !AD_CHAR( *p ) ) { 4456 return LDAP_INVALID_SYNTAX; 4457 } 4458 } 4459 4460 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) { 4461 return LDAP_INVALID_SYNTAX; 4462 } 4463 4464 p++; 4465 4466 if (p != e) { 4467 return LDAP_INVALID_SYNTAX; 4468 } 4469 4470 return LDAP_SUCCESS; 4471 } 4472 4473 static int 4474 bootParameterValidate( 4475 Syntax *syntax, 4476 struct berval *val ) 4477 { 4478 char *p, *e; 4479 4480 if ( BER_BVISEMPTY( val ) ) { 4481 return LDAP_INVALID_SYNTAX; 4482 } 4483 4484 p = (char *)val->bv_val; 4485 e = p + val->bv_len; 4486 4487 /* key */ 4488 for (; ( p < e ) && ( *p != '=' ); p++ ) { 4489 if ( !AD_CHAR( *p ) ) { 4490 return LDAP_INVALID_SYNTAX; 4491 } 4492 } 4493 4494 if ( *p != '=' ) { 4495 return LDAP_INVALID_SYNTAX; 4496 } 4497 4498 /* server */ 4499 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) { 4500 if ( !AD_CHAR( *p ) ) { 4501 return LDAP_INVALID_SYNTAX; 4502 } 4503 } 4504 4505 if ( *p != ':' ) { 4506 return LDAP_INVALID_SYNTAX; 4507 } 4508 4509 /* path */ 4510 for ( p++; p < e; p++ ) { 4511 if ( !SLAP_PRINTABLE( *p ) ) { 4512 return LDAP_INVALID_SYNTAX; 4513 } 4514 } 4515 4516 return LDAP_SUCCESS; 4517 } 4518 4519 static int 4520 firstComponentNormalize( 4521 slap_mask_t usage, 4522 Syntax *syntax, 4523 MatchingRule *mr, 4524 struct berval *val, 4525 struct berval *normalized, 4526 void *ctx ) 4527 { 4528 int rc; 4529 struct berval comp; 4530 ber_len_t len; 4531 4532 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) { 4533 ber_dupbv_x( normalized, val, ctx ); 4534 return LDAP_SUCCESS; 4535 } 4536 4537 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4538 4539 if( val->bv_val[0] != '(' /*')'*/ && 4540 val->bv_val[0] != '{' /*'}'*/ ) 4541 { 4542 return LDAP_INVALID_SYNTAX; 4543 } 4544 4545 /* trim leading white space */ 4546 for( len=1; 4547 len < val->bv_len && ASCII_SPACE(val->bv_val[len]); 4548 len++ ) 4549 { 4550 /* empty */ 4551 } 4552 4553 /* grab next word */ 4554 comp.bv_val = &val->bv_val[len]; 4555 len = val->bv_len - len; 4556 for( comp.bv_len = 0; 4557 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len; 4558 comp.bv_len++ ) 4559 { 4560 /* empty */ 4561 } 4562 4563 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) { 4564 rc = numericoidValidate( NULL, &comp ); 4565 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) { 4566 rc = integerValidate( NULL, &comp ); 4567 } else { 4568 rc = LDAP_INVALID_SYNTAX; 4569 } 4570 4571 4572 if( rc == LDAP_SUCCESS ) { 4573 ber_dupbv_x( normalized, &comp, ctx ); 4574 } 4575 4576 return rc; 4577 } 4578 4579 static char *country_gen_syn[] = { 4580 "1.3.6.1.4.1.1466.115.121.1.15", 4581 "1.3.6.1.4.1.1466.115.121.1.26", 4582 "1.3.6.1.4.1.1466.115.121.1.44", 4583 NULL 4584 }; 4585 4586 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " 4587 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " 4588 4589 static slap_syntax_defs_rec syntax_defs[] = { 4590 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " 4591 X_BINARY X_NOT_H_R ")", 4592 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL}, 4593 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")", 4594 0, NULL, NULL, NULL}, 4595 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", 4596 0, NULL, NULL, NULL}, 4597 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " 4598 X_NOT_H_R ")", 4599 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 4600 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " 4601 X_NOT_H_R ")", 4602 SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 4603 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", 4604 0, NULL, bitStringValidate, NULL }, 4605 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", 4606 0, NULL, booleanValidate, NULL}, 4607 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " 4608 X_BINARY X_NOT_H_R ")", 4609 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4610 NULL, certificateValidate, NULL}, 4611 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " 4612 X_BINARY X_NOT_H_R ")", 4613 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4614 NULL, certificateListValidate, NULL}, 4615 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " 4616 X_BINARY X_NOT_H_R ")", 4617 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 4618 NULL, sequenceValidate, NULL}, 4619 #if 0 /* need to go __after__ printableString */ 4620 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 4621 0, "1.3.6.1.4.1.1466.115.121.1.44", 4622 countryStringValidate, NULL}, 4623 #endif 4624 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", 4625 0, NULL, dnValidate, dnPretty}, 4626 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )", 4627 0, NULL, rdnValidate, rdnPretty}, 4628 #ifdef LDAP_COMP_MATCH 4629 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", 4630 0, NULL, allComponentsValidate, NULL}, 4631 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ", 4632 0, NULL, componentFilterValidate, NULL}, 4633 #endif 4634 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )", 4635 0, NULL, NULL, NULL}, 4636 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", 4637 0, NULL, deliveryMethodValidate, NULL}, 4638 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", 4639 0, NULL, UTF8StringValidate, NULL}, 4640 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", 4641 0, NULL, NULL, NULL}, 4642 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", 4643 0, NULL, NULL, NULL}, 4644 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )", 4645 0, NULL, NULL, NULL}, 4646 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )", 4647 0, NULL, NULL, NULL}, 4648 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", 4649 0, NULL, NULL, NULL}, 4650 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", 4651 0, NULL, printablesStringValidate, NULL}, 4652 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")", 4653 SLAP_SYNTAX_BLOB, NULL, NULL, NULL}, 4654 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", 4655 0, NULL, generalizedTimeValidate, NULL}, 4656 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", 4657 0, NULL, NULL, NULL}, 4658 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", 4659 0, NULL, IA5StringValidate, NULL}, 4660 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", 4661 0, NULL, integerValidate, NULL}, 4662 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")", 4663 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 4664 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )", 4665 0, NULL, NULL, NULL}, 4666 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", 4667 0, NULL, NULL, NULL}, 4668 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", 4669 0, NULL, NULL, NULL}, 4670 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", 4671 0, NULL, NULL, NULL}, 4672 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", 4673 0, NULL, NULL, NULL}, 4674 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", 4675 0, NULL, nameUIDValidate, nameUIDPretty }, 4676 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", 4677 0, NULL, NULL, NULL}, 4678 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", 4679 0, NULL, numericStringValidate, NULL}, 4680 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", 4681 0, NULL, NULL, NULL}, 4682 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", 4683 0, NULL, numericoidValidate, NULL}, 4684 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", 4685 0, NULL, IA5StringValidate, NULL}, 4686 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", 4687 0, NULL, blobValidate, NULL}, 4688 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", 4689 0, NULL, UTF8StringValidate, NULL}, 4690 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", 4691 0, NULL, NULL, NULL}, 4692 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", 4693 0, NULL, NULL, NULL}, 4694 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", 4695 0, NULL, printableStringValidate, NULL}, 4696 /* moved here because now depends on Directory String, IA5 String 4697 * and Printable String */ 4698 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 4699 0, country_gen_syn, countryStringValidate, NULL}, 4700 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )", 4701 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */ 4702 0, NULL, subtreeSpecificationValidate, NULL}, 4703 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " 4704 X_BINARY X_NOT_H_R ")", 4705 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 4706 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", 4707 0, NULL, printableStringValidate, NULL}, 4708 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", 4709 0, NULL, NULL, NULL}, 4710 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", 4711 0, NULL, printablesStringValidate, NULL}, 4712 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 4713 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", 4714 0, NULL, utcTimeValidate, NULL}, 4715 #endif 4716 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", 4717 0, NULL, NULL, NULL}, 4718 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )", 4719 0, NULL, NULL, NULL}, 4720 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )", 4721 0, NULL, NULL, NULL}, 4722 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )", 4723 0, NULL, NULL, NULL}, 4724 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", 4725 0, NULL, NULL, NULL}, 4726 4727 /* RFC 2307 NIS Syntaxes */ 4728 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )", 4729 0, NULL, nisNetgroupTripleValidate, NULL}, 4730 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", 4731 0, NULL, bootParameterValidate, NULL}, 4732 4733 /* draft-zeilenga-ldap-x509 */ 4734 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )", 4735 SLAP_SYNTAX_HIDE, NULL, 4736 serialNumberAndIssuerValidate, 4737 serialNumberAndIssuerPretty}, 4738 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )", 4739 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4740 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )", 4741 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4742 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )", 4743 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4744 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )", 4745 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4746 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )", 4747 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4748 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )", 4749 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4750 4751 #ifdef SLAPD_AUTHPASSWD 4752 /* needs updating */ 4753 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )", 4754 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 4755 #endif 4756 4757 {"( 1.3.6.1.1.16.1 DESC 'UUID' )", 4758 0, NULL, UUIDValidate, UUIDPretty}, 4759 4760 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )", 4761 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty }, 4762 4763 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )", 4764 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty }, 4765 4766 /* OpenLDAP Void Syntax */ 4767 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , 4768 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL}, 4769 4770 /* FIXME: OID is unused, but not registered yet */ 4771 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )", 4772 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty}, 4773 4774 {NULL, 0, NULL, NULL, NULL} 4775 }; 4776 4777 char *csnSIDMatchSyntaxes[] = { 4778 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */, 4779 NULL 4780 }; 4781 char *certificateExactMatchSyntaxes[] = { 4782 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 4783 NULL 4784 }; 4785 #ifdef LDAP_COMP_MATCH 4786 char *componentFilterMatchSyntaxes[] = { 4787 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 4788 NULL 4789 }; 4790 #endif 4791 char *directoryStringSyntaxes[] = { 4792 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */, 4793 NULL 4794 }; 4795 char *integerFirstComponentMatchSyntaxes[] = { 4796 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */, 4797 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */, 4798 NULL 4799 }; 4800 char *objectIdentifierFirstComponentMatchSyntaxes[] = { 4801 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */, 4802 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */, 4803 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */, 4804 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */, 4805 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */, 4806 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */, 4807 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */, 4808 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */, 4809 NULL 4810 }; 4811 4812 /* 4813 * Other matching rules in X.520 that we do not use (yet): 4814 * 4815 * 2.5.13.25 uTCTimeMatch 4816 * 2.5.13.26 uTCTimeOrderingMatch 4817 * 2.5.13.31* directoryStringFirstComponentMatch 4818 * 2.5.13.32* wordMatch 4819 * 2.5.13.33* keywordMatch 4820 * 2.5.13.36+ certificatePairExactMatch 4821 * 2.5.13.37+ certificatePairMatch 4822 * 2.5.13.38+ certificateListExactMatch 4823 * 2.5.13.39+ certificateListMatch 4824 * 2.5.13.40+ algorithmIdentifierMatch 4825 * 2.5.13.41* storedPrefixMatch 4826 * 2.5.13.42 attributeCertificateMatch 4827 * 2.5.13.43 readerAndKeyIDMatch 4828 * 2.5.13.44 attributeIntegrityMatch 4829 * 4830 * (*) described in RFC 3698 (LDAP: Additional Matching Rules) 4831 * (+) described in draft-zeilenga-ldap-x509 4832 */ 4833 static slap_mrule_defs_rec mrule_defs[] = { 4834 /* 4835 * EQUALITY matching rules must be listed after associated APPROX 4836 * matching rules. So, we list all APPROX matching rules first. 4837 */ 4838 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' " 4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4840 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 4841 NULL, NULL, directoryStringApproxMatch, 4842 directoryStringApproxIndexer, directoryStringApproxFilter, 4843 NULL}, 4844 4845 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' " 4846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 4847 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 4848 NULL, NULL, IA5StringApproxMatch, 4849 IA5StringApproxIndexer, IA5StringApproxFilter, 4850 NULL}, 4851 4852 /* 4853 * Other matching rules 4854 */ 4855 4856 {"( 2.5.13.0 NAME 'objectIdentifierMatch' " 4857 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 4858 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4859 NULL, NULL, octetStringMatch, 4860 octetStringIndexer, octetStringFilter, 4861 NULL }, 4862 4863 {"( 2.5.13.1 NAME 'distinguishedNameMatch' " 4864 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4865 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4866 NULL, dnNormalize, dnMatch, 4867 octetStringIndexer, octetStringFilter, 4868 NULL }, 4869 4870 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' " 4871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4872 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4873 NULL, dnNormalize, dnRelativeMatch, 4874 NULL, NULL, 4875 NULL }, 4876 4877 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' " 4878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4879 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4880 NULL, dnNormalize, dnRelativeMatch, 4881 NULL, NULL, 4882 NULL }, 4883 4884 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' " 4885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4886 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4887 NULL, dnNormalize, dnRelativeMatch, 4888 NULL, NULL, 4889 NULL }, 4890 4891 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' " 4892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 4893 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 4894 NULL, dnNormalize, dnRelativeMatch, 4895 NULL, NULL, 4896 NULL }, 4897 4898 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' " 4899 "SYNTAX 1.2.36.79672281.1.5.0 )", 4900 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4901 NULL, rdnNormalize, rdnMatch, 4902 octetStringIndexer, octetStringFilter, 4903 NULL }, 4904 4905 #ifdef LDAP_COMP_MATCH 4906 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' " 4907 "SYNTAX 1.2.36.79672281.1.5.2 )", 4908 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes, 4909 NULL, NULL , componentFilterMatch, 4910 octetStringIndexer, octetStringFilter, 4911 NULL }, 4912 4913 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' " 4914 "SYNTAX 1.2.36.79672281.1.5.3 )", 4915 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 4916 NULL, NULL , allComponentsMatch, 4917 octetStringIndexer, octetStringFilter, 4918 NULL }, 4919 4920 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' " 4921 "SYNTAX 1.2.36.79672281.1.5.3 )", 4922 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 4923 NULL, NULL , directoryComponentsMatch, 4924 octetStringIndexer, octetStringFilter, 4925 NULL }, 4926 #endif 4927 4928 {"( 2.5.13.2 NAME 'caseIgnoreMatch' " 4929 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4930 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 4931 NULL, UTF8StringNormalize, octetStringMatch, 4932 octetStringIndexer, octetStringFilter, 4933 directoryStringApproxMatchOID }, 4934 4935 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' " 4936 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4937 SLAP_MR_ORDERING, directoryStringSyntaxes, 4938 NULL, UTF8StringNormalize, octetStringOrderingMatch, 4939 NULL, NULL, 4940 "caseIgnoreMatch" }, 4941 4942 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " 4943 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4944 SLAP_MR_SUBSTR, directoryStringSyntaxes, 4945 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 4946 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4947 "caseIgnoreMatch" }, 4948 4949 {"( 2.5.13.5 NAME 'caseExactMatch' " 4950 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4951 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 4952 NULL, UTF8StringNormalize, octetStringMatch, 4953 octetStringIndexer, octetStringFilter, 4954 directoryStringApproxMatchOID }, 4955 4956 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' " 4957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 4958 SLAP_MR_ORDERING, directoryStringSyntaxes, 4959 NULL, UTF8StringNormalize, octetStringOrderingMatch, 4960 NULL, NULL, 4961 "caseExactMatch" }, 4962 4963 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " 4964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4965 SLAP_MR_SUBSTR, directoryStringSyntaxes, 4966 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 4967 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4968 "caseExactMatch" }, 4969 4970 {"( 2.5.13.8 NAME 'numericStringMatch' " 4971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 4972 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4973 NULL, numericStringNormalize, octetStringMatch, 4974 octetStringIndexer, octetStringFilter, 4975 NULL }, 4976 4977 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' " 4978 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 4979 SLAP_MR_ORDERING, NULL, 4980 NULL, numericStringNormalize, octetStringOrderingMatch, 4981 NULL, NULL, 4982 "numericStringMatch" }, 4983 4984 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' " 4985 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4986 SLAP_MR_SUBSTR, NULL, 4987 NULL, numericStringNormalize, octetStringSubstringsMatch, 4988 octetStringSubstringsIndexer, octetStringSubstringsFilter, 4989 "numericStringMatch" }, 4990 4991 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' " 4992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", 4993 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 4994 NULL, NULL, NULL, NULL, NULL, NULL }, 4995 4996 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' " 4997 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 4998 SLAP_MR_SUBSTR, NULL, 4999 NULL, NULL, NULL, NULL, NULL, 5000 "caseIgnoreListMatch" }, 5001 5002 {"( 2.5.13.13 NAME 'booleanMatch' " 5003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )", 5004 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5005 NULL, NULL, booleanMatch, 5006 octetStringIndexer, octetStringFilter, 5007 NULL }, 5008 5009 {"( 2.5.13.14 NAME 'integerMatch' " 5010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5011 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 5012 NULL, NULL, integerMatch, 5013 integerIndexer, integerFilter, 5014 NULL }, 5015 5016 {"( 2.5.13.15 NAME 'integerOrderingMatch' " 5017 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5018 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 5019 NULL, NULL, integerMatch, 5020 NULL, NULL, 5021 "integerMatch" }, 5022 5023 {"( 2.5.13.16 NAME 'bitStringMatch' " 5024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", 5025 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5026 NULL, NULL, octetStringMatch, 5027 octetStringIndexer, octetStringFilter, 5028 NULL }, 5029 5030 {"( 2.5.13.17 NAME 'octetStringMatch' " 5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5032 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5033 NULL, NULL, octetStringMatch, 5034 octetStringIndexer, octetStringFilter, 5035 NULL }, 5036 5037 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' " 5038 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5039 SLAP_MR_ORDERING, NULL, 5040 NULL, NULL, octetStringOrderingMatch, 5041 NULL, NULL, 5042 "octetStringMatch" }, 5043 5044 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' " 5045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5046 SLAP_MR_SUBSTR, NULL, 5047 NULL, NULL, octetStringSubstringsMatch, 5048 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5049 "octetStringMatch" }, 5050 5051 {"( 2.5.13.20 NAME 'telephoneNumberMatch' " 5052 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", 5053 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5054 NULL, 5055 telephoneNumberNormalize, octetStringMatch, 5056 octetStringIndexer, octetStringFilter, 5057 NULL }, 5058 5059 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' " 5060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 5061 SLAP_MR_SUBSTR, NULL, 5062 NULL, telephoneNumberNormalize, octetStringSubstringsMatch, 5063 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5064 "telephoneNumberMatch" }, 5065 5066 {"( 2.5.13.22 NAME 'presentationAddressMatch' " 5067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", 5068 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5069 NULL, NULL, NULL, NULL, NULL, NULL }, 5070 5071 {"( 2.5.13.23 NAME 'uniqueMemberMatch' " 5072 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", 5073 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5074 NULL, uniqueMemberNormalize, uniqueMemberMatch, 5075 uniqueMemberIndexer, uniqueMemberFilter, 5076 NULL }, 5077 5078 {"( 2.5.13.24 NAME 'protocolInformationMatch' " 5079 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", 5080 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5081 NULL, NULL, NULL, NULL, NULL, NULL }, 5082 5083 {"( 2.5.13.27 NAME 'generalizedTimeMatch' " 5084 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 5085 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 5086 NULL, generalizedTimeNormalize, octetStringMatch, 5087 generalizedTimeIndexer, generalizedTimeFilter, 5088 NULL }, 5089 5090 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " 5091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 5092 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 5093 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch, 5094 NULL, NULL, 5095 "generalizedTimeMatch" }, 5096 5097 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' " 5098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5099 SLAP_MR_EQUALITY | SLAP_MR_EXT, 5100 integerFirstComponentMatchSyntaxes, 5101 NULL, firstComponentNormalize, integerMatch, 5102 octetStringIndexer, octetStringFilter, 5103 NULL }, 5104 5105 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' " 5106 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 5107 SLAP_MR_EQUALITY | SLAP_MR_EXT, 5108 objectIdentifierFirstComponentMatchSyntaxes, 5109 NULL, firstComponentNormalize, octetStringMatch, 5110 octetStringIndexer, octetStringFilter, 5111 NULL }, 5112 5113 {"( 2.5.13.34 NAME 'certificateExactMatch' " 5114 "SYNTAX 1.3.6.1.1.15.1 )", 5115 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, 5116 NULL, certificateExactNormalize, octetStringMatch, 5117 octetStringIndexer, octetStringFilter, 5118 NULL }, 5119 5120 {"( 2.5.13.35 NAME 'certificateMatch' " 5121 "SYNTAX 1.3.6.1.1.15.2 )", 5122 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5123 NULL, NULL, NULL, NULL, NULL, 5124 NULL }, 5125 5126 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " 5127 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5128 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5129 NULL, IA5StringNormalize, octetStringMatch, 5130 octetStringIndexer, octetStringFilter, 5131 IA5StringApproxMatchOID }, 5132 5133 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' " 5134 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5135 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 5136 NULL, IA5StringNormalize, octetStringMatch, 5137 octetStringIndexer, octetStringFilter, 5138 IA5StringApproxMatchOID }, 5139 5140 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' " 5141 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5142 SLAP_MR_SUBSTR, NULL, 5143 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 5144 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5145 "caseIgnoreIA5Match" }, 5146 5147 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' " 5148 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 5149 SLAP_MR_SUBSTR, NULL, 5150 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 5151 octetStringSubstringsIndexer, octetStringSubstringsFilter, 5152 "caseExactIA5Match" }, 5153 5154 #ifdef SLAPD_AUTHPASSWD 5155 /* needs updating */ 5156 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' " 5157 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 5158 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 5159 NULL, NULL, authPasswordMatch, 5160 NULL, NULL, 5161 NULL}, 5162 #endif 5163 5164 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' " 5165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5166 SLAP_MR_EXT, NULL, 5167 NULL, NULL, integerBitAndMatch, 5168 NULL, NULL, 5169 "integerMatch" }, 5170 5171 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' " 5172 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 5173 SLAP_MR_EXT, NULL, 5174 NULL, NULL, integerBitOrMatch, 5175 NULL, NULL, 5176 "integerMatch" }, 5177 5178 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' " 5179 "SYNTAX 1.3.6.1.1.16.1 )", 5180 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL, 5181 NULL, UUIDNormalize, octetStringMatch, 5182 octetStringIndexer, octetStringFilter, 5183 NULL}, 5184 5185 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' " 5186 "SYNTAX 1.3.6.1.1.16.1 )", 5187 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL, 5188 NULL, UUIDNormalize, octetStringOrderingMatch, 5189 octetStringIndexer, octetStringFilter, 5190 "UUIDMatch"}, 5191 5192 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' " 5193 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 5194 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL, 5195 NULL, csnNormalize, csnMatch, 5196 csnIndexer, csnFilter, 5197 NULL}, 5198 5199 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' " 5200 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 5201 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 5202 NULL, NULL, csnOrderingMatch, 5203 NULL, NULL, 5204 "CSNMatch" }, 5205 5206 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' " 5207 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )", 5208 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes, 5209 NULL, csnSidNormalize, octetStringMatch, 5210 octetStringIndexer, octetStringFilter, 5211 NULL }, 5212 5213 /* FIXME: OID is unused, but not registered yet */ 5214 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' " 5215 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", 5216 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 5217 NULL, authzNormalize, authzMatch, 5218 NULL, NULL, 5219 NULL}, 5220 5221 {NULL, SLAP_MR_NONE, NULL, 5222 NULL, NULL, NULL, NULL, NULL, 5223 NULL } 5224 }; 5225 5226 int 5227 slap_schema_init( void ) 5228 { 5229 int res; 5230 int i; 5231 5232 /* we should only be called once (from main) */ 5233 assert( schema_init_done == 0 ); 5234 5235 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { 5236 res = register_syntax( &syntax_defs[i] ); 5237 5238 if ( res ) { 5239 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n", 5240 syntax_defs[i].sd_desc ); 5241 return LDAP_OTHER; 5242 } 5243 } 5244 5245 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) { 5246 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE && 5247 mrule_defs[i].mrd_compat_syntaxes == NULL ) 5248 { 5249 fprintf( stderr, 5250 "slap_schema_init: Ignoring unusable matching rule %s\n", 5251 mrule_defs[i].mrd_desc ); 5252 continue; 5253 } 5254 5255 res = register_matching_rule( &mrule_defs[i] ); 5256 5257 if ( res ) { 5258 fprintf( stderr, 5259 "slap_schema_init: Error registering matching rule %s\n", 5260 mrule_defs[i].mrd_desc ); 5261 return LDAP_OTHER; 5262 } 5263 } 5264 5265 res = slap_schema_load(); 5266 schema_init_done = 1; 5267 return res; 5268 } 5269 5270 void 5271 schema_destroy( void ) 5272 { 5273 oidm_destroy(); 5274 oc_destroy(); 5275 at_destroy(); 5276 mr_destroy(); 5277 mru_destroy(); 5278 syn_destroy(); 5279 5280 if( schema_init_done ) { 5281 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex ); 5282 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex ); 5283 } 5284 } 5285