1 /* $NetBSD: schema_init.c,v 1.1.1.3 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* schema_init.c - init builtin schema */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/schema_init.c,v 1.386.2.37 2009/11/17 17:18:11 quanah Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2009 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19 #include "portable.h" 20 21 #include <stdio.h> 22 #ifdef HAVE_LIMITS_H 23 #include <limits.h> 24 #endif 25 26 #include <ac/ctype.h> 27 #include <ac/errno.h> 28 #include <ac/string.h> 29 #include <ac/socket.h> 30 31 #include "slap.h" 32 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */ 33 34 #include "ldap_utf8.h" 35 36 #include "lutil.h" 37 #include "lutil_hash.h" 38 #define HASH_BYTES LUTIL_HASH_BYTES 39 #define HASH_CONTEXT lutil_HASH_CTX 40 #define HASH_Init(c) lutil_HASHInit(c) 41 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len) 42 #define HASH_Final(d,c) lutil_HASHFinal(d,c) 43 44 /* approx matching rules */ 45 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4" 46 #define directoryStringApproxMatch approxMatch 47 #define directoryStringApproxIndexer approxIndexer 48 #define directoryStringApproxFilter approxFilter 49 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5" 50 #define IA5StringApproxMatch approxMatch 51 #define IA5StringApproxIndexer approxIndexer 52 #define IA5StringApproxFilter approxFilter 53 54 /* Change Sequence Number (CSN) - much of this will change */ 55 #define csnMatch octetStringMatch 56 #define csnOrderingMatch octetStringOrderingMatch 57 #define csnIndexer generalizedTimeIndexer 58 #define csnFilter generalizedTimeFilter 59 60 #define authzMatch octetStringMatch 61 62 /* X.509 PMI ldapSyntaxes */ 63 /* FIXME: need to create temporary OIDs under OpenLDAP's arc; 64 * these are currently hijacked 65 * 66 * 1.3.6.1.4.1.4203.666 OpenLDAP 67 * 1.3.6.1.4.1.4203.666.11 self-contained works 68 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI 69 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes 70 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported) 71 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported) 72 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported) 73 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema) 74 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema) 75 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema) 76 */ 77 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */ 78 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5" 79 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6" 80 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7" 81 #else /* from OpenLDAP's experimental oid arc */ 82 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2" 83 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1" 84 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2" 85 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3" 86 #endif 87 88 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT; 89 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT; 90 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT; 91 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT; 92 93 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT; 94 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( 95 SLAP_INDEX_INTLEN_DEFAULT ); 96 97 ldap_pvt_thread_mutex_t ad_undef_mutex; 98 ldap_pvt_thread_mutex_t oc_undef_mutex; 99 100 static int 101 generalizedTimeValidate( 102 Syntax *syntax, 103 struct berval *in ); 104 105 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 106 static int 107 utcTimeValidate( 108 Syntax *syntax, 109 struct berval *in ); 110 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ 111 112 static int 113 inValidate( 114 Syntax *syntax, 115 struct berval *in ) 116 { 117 /* no value allowed */ 118 return LDAP_INVALID_SYNTAX; 119 } 120 121 static int 122 blobValidate( 123 Syntax *syntax, 124 struct berval *in ) 125 { 126 /* any value allowed */ 127 return LDAP_SUCCESS; 128 } 129 130 #define berValidate blobValidate 131 132 static int 133 sequenceValidate( 134 Syntax *syntax, 135 struct berval *in ) 136 { 137 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX; 138 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 139 140 return LDAP_SUCCESS; 141 } 142 143 /* X.509 related stuff */ 144 145 enum { 146 SLAP_X509_V1 = 0, 147 SLAP_X509_V2 = 1, 148 SLAP_X509_V3 = 2 149 }; 150 151 enum { 152 SLAP_TAG_UTCTIME = 0x17U, 153 SLAP_TAG_GENERALIZEDTIME = 0x18U 154 }; 155 156 157 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) 158 159 enum { 160 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0, 161 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1, 162 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2, 163 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3 164 }; 165 166 enum { 167 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0 168 }; 169 170 /* 171 GeneralName ::= CHOICE { 172 otherName [0] INSTANCE OF OTHER-NAME, 173 rfc822Name [1] IA5String, 174 dNSName [2] IA5String, 175 x400Address [3] ORAddress, 176 directoryName [4] Name, 177 ediPartyName [5] EDIPartyName, 178 uniformResourceIdentifier [6] IA5String, 179 iPAddress [7] OCTET STRING, 180 registeredID [8] OBJECT IDENTIFIER } 181 */ 182 enum { 183 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0, 184 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1, 185 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2, 186 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3, 187 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4, 188 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5, 189 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6, 190 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7, 191 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8 192 }; 193 194 /* X.509 PMI related stuff */ 195 enum { 196 SLAP_X509AC_V1 = 0, 197 SLAP_X509AC_V2 = 1 198 }; 199 200 enum { 201 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0 202 }; 203 204 /* X.509 certificate validation */ 205 static int 206 certificateValidate( Syntax *syntax, struct berval *in ) 207 { 208 BerElementBuffer berbuf; 209 BerElement *ber = (BerElement *)&berbuf; 210 ber_tag_t tag; 211 ber_len_t len; 212 ber_int_t version = SLAP_X509_V1; 213 214 ber_init2( ber, in, LBER_USE_DER ); 215 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 216 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 217 tag = ber_skip_tag( ber, &len ); /* Sequence */ 218 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 219 tag = ber_peek_tag( ber, &len ); 220 /* Optional version */ 221 if ( tag == SLAP_X509_OPT_C_VERSION ) { 222 tag = ber_skip_tag( ber, &len ); 223 tag = ber_get_int( ber, &version ); 224 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 225 } 226 /* NOTE: don't try to parse Serial, because it might be longer 227 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */ 228 tag = ber_skip_tag( ber, &len ); /* Serial */ 229 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 230 ber_skip_data( ber, len ); 231 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 232 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 233 ber_skip_data( ber, len ); 234 tag = ber_skip_tag( ber, &len ); /* Issuer DN */ 235 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 236 ber_skip_data( ber, len ); 237 tag = ber_skip_tag( ber, &len ); /* Validity */ 238 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 239 ber_skip_data( ber, len ); 240 tag = ber_skip_tag( ber, &len ); /* Subject DN */ 241 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 242 ber_skip_data( ber, len ); 243 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */ 244 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 245 ber_skip_data( ber, len ); 246 tag = ber_skip_tag( ber, &len ); 247 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */ 248 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 249 ber_skip_data( ber, len ); 250 tag = ber_skip_tag( ber, &len ); 251 } 252 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */ 253 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 254 ber_skip_data( ber, len ); 255 tag = ber_skip_tag( ber, &len ); 256 } 257 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */ 258 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX; 259 tag = ber_skip_tag( ber, &len ); 260 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 261 ber_skip_data( ber, len ); 262 tag = ber_skip_tag( ber, &len ); 263 } 264 /* signatureAlgorithm */ 265 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 266 ber_skip_data( ber, len ); 267 tag = ber_skip_tag( ber, &len ); 268 /* Signature */ 269 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 270 ber_skip_data( ber, len ); 271 tag = ber_skip_tag( ber, &len ); 272 /* Must be at end now */ 273 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX; 274 return LDAP_SUCCESS; 275 } 276 277 /* X.509 certificate list validation */ 278 static int 279 checkTime( struct berval *in, struct berval *out ); 280 281 static int 282 certificateListValidate( Syntax *syntax, struct berval *in ) 283 { 284 BerElementBuffer berbuf; 285 BerElement *ber = (BerElement *)&berbuf; 286 ber_tag_t tag; 287 ber_len_t len, wrapper_len; 288 char *wrapper_start; 289 int wrapper_ok = 0; 290 ber_int_t version = SLAP_X509_V1; 291 struct berval bvdn, bvtu; 292 293 ber_init2( ber, in, LBER_USE_DER ); 294 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */ 295 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 296 wrapper_start = ber->ber_ptr; 297 tag = ber_skip_tag( ber, &len ); /* Sequence */ 298 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 299 tag = ber_peek_tag( ber, &len ); 300 /* Optional version */ 301 if ( tag == LBER_INTEGER ) { 302 tag = ber_get_int( ber, &version ); 303 assert( tag == LBER_INTEGER ); 304 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 305 } 306 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 307 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 308 ber_skip_data( ber, len ); 309 tag = ber_peek_tag( ber, &len ); /* Issuer DN */ 310 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 311 len = ber_ptrlen( ber ); 312 bvdn.bv_val = in->bv_val + len; 313 bvdn.bv_len = in->bv_len - len; 314 tag = ber_skip_tag( ber, &len ); 315 ber_skip_data( ber, len ); 316 tag = ber_skip_tag( ber, &len ); /* thisUpdate */ 317 /* Time is a CHOICE { UTCTime, GeneralizedTime } */ 318 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX; 319 bvtu.bv_val = (char *)ber->ber_ptr; 320 bvtu.bv_len = len; 321 ber_skip_data( ber, len ); 322 /* Optional nextUpdate */ 323 tag = ber_skip_tag( ber, &len ); 324 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) { 325 ber_skip_data( ber, len ); 326 tag = ber_skip_tag( ber, &len ); 327 } 328 /* revokedCertificates - Sequence of Sequence, Optional */ 329 if ( tag == LBER_SEQUENCE ) { 330 ber_len_t seqlen; 331 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) { 332 /* Should NOT be empty */ 333 ber_skip_data( ber, len ); 334 tag = ber_skip_tag( ber, &len ); 335 } 336 } 337 /* Optional Extensions - Sequence of Sequence */ 338 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */ 339 ber_len_t seqlen; 340 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 341 tag = ber_peek_tag( ber, &seqlen ); 342 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 343 ber_skip_data( ber, len ); 344 tag = ber_skip_tag( ber, &len ); 345 } 346 /* signatureAlgorithm */ 347 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 348 ber_skip_data( ber, len ); 349 tag = ber_skip_tag( ber, &len ); 350 /* Signature */ 351 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; 352 ber_skip_data( ber, len ); 353 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1; 354 tag = ber_skip_tag( ber, &len ); 355 /* Must be at end now */ 356 /* NOTE: OpenSSL tolerates CL with garbage past the end */ 357 if ( len || tag != LBER_DEFAULT ) { 358 struct berval issuer_dn = BER_BVNULL, thisUpdate; 359 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 360 int rc; 361 362 if ( ! wrapper_ok ) { 363 return LDAP_INVALID_SYNTAX; 364 } 365 366 rc = dnX509normalize( &bvdn, &issuer_dn ); 367 if ( rc != LDAP_SUCCESS ) { 368 rc = LDAP_INVALID_SYNTAX; 369 goto done; 370 } 371 372 thisUpdate.bv_val = tubuf; 373 thisUpdate.bv_len = sizeof(tubuf); 374 if ( checkTime( &bvtu, &thisUpdate ) ) { 375 rc = LDAP_INVALID_SYNTAX; 376 goto done; 377 } 378 379 Debug( LDAP_DEBUG_ANY, 380 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n", 381 issuer_dn.bv_val, thisUpdate.bv_val, 0 ); 382 383 done:; 384 if ( ! BER_BVISNULL( &issuer_dn ) ) { 385 ber_memfree( issuer_dn.bv_val ); 386 } 387 388 return rc; 389 } 390 391 return LDAP_SUCCESS; 392 } 393 394 /* X.509 PMI Attribute Certificate Validate */ 395 static int 396 attributeCertificateValidate( Syntax *syntax, struct berval *in ) 397 { 398 BerElementBuffer berbuf; 399 BerElement *ber = (BerElement *)&berbuf; 400 ber_tag_t tag; 401 ber_len_t len; 402 ber_int_t version; 403 int cont = 0; 404 405 ber_init2( ber, in, LBER_USE_DER ); 406 407 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 408 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 409 410 tag = ber_skip_tag( ber, &len ); /* Sequence */ 411 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 412 413 tag = ber_peek_tag( ber, &len ); /* Version */ 414 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 415 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */ 416 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX; 417 418 tag = ber_skip_tag( ber, &len ); /* Holder */ 419 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 420 ber_skip_data( ber, len ); 421 422 tag = ber_skip_tag( ber, &len ); /* Issuer */ 423 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX; 424 ber_skip_data( ber, len ); 425 426 tag = ber_skip_tag( ber, &len ); /* Signature */ 427 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 428 ber_skip_data( ber, len ); 429 430 tag = ber_skip_tag( ber, &len ); /* Serial number */ 431 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; 432 ber_skip_data( ber, len ); 433 434 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */ 435 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 436 ber_skip_data( ber, len ); 437 438 tag = ber_skip_tag( ber, &len ); /* Attributes */ 439 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 440 ber_skip_data( ber, len ); 441 442 tag = ber_peek_tag( ber, &len ); 443 444 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */ 445 tag = ber_skip_tag( ber, &len ); 446 ber_skip_data( ber, len ); 447 tag = ber_peek_tag( ber, &len ); 448 } 449 450 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */ 451 tag = ber_skip_tag( ber, &len ); 452 ber_skip_data( ber, len ); 453 cont++; 454 tag = ber_peek_tag( ber, &len ); 455 } 456 457 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */ 458 tag = ber_skip_tag( ber, &len ); 459 ber_skip_data( ber, len ); 460 cont++; 461 tag = ber_peek_tag( ber, &len ); 462 } 463 464 if ( tag == LBER_BITSTRING ) { /* Signature */ 465 tag = ber_skip_tag( ber, &len ); 466 ber_skip_data( ber, len ); 467 cont++; 468 tag = ber_peek_tag( ber, &len ); 469 } 470 471 /* Must be at end now */ 472 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX; 473 474 return LDAP_SUCCESS; 475 } 476 477 int 478 octetStringMatch( 479 int *matchp, 480 slap_mask_t flags, 481 Syntax *syntax, 482 MatchingRule *mr, 483 struct berval *value, 484 void *assertedValue ) 485 { 486 struct berval *asserted = (struct berval *) assertedValue; 487 int match = value->bv_len - asserted->bv_len; 488 489 if( match == 0 ) { 490 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len ); 491 } 492 493 *matchp = match; 494 return LDAP_SUCCESS; 495 } 496 497 int 498 octetStringOrderingMatch( 499 int *matchp, 500 slap_mask_t flags, 501 Syntax *syntax, 502 MatchingRule *mr, 503 struct berval *value, 504 void *assertedValue ) 505 { 506 struct berval *asserted = (struct berval *) assertedValue; 507 ber_len_t v_len = value->bv_len; 508 ber_len_t av_len = asserted->bv_len; 509 510 int match = memcmp( value->bv_val, asserted->bv_val, 511 (v_len < av_len ? v_len : av_len) ); 512 513 if( match == 0 ) match = v_len - av_len; 514 515 *matchp = match; 516 return LDAP_SUCCESS; 517 } 518 519 static void 520 hashPreset( 521 HASH_CONTEXT *HASHcontext, 522 struct berval *prefix, 523 char pre, 524 Syntax *syntax, 525 MatchingRule *mr) 526 { 527 HASH_Init(HASHcontext); 528 if(prefix && prefix->bv_len > 0) { 529 HASH_Update(HASHcontext, 530 (unsigned char *)prefix->bv_val, prefix->bv_len); 531 } 532 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre)); 533 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen); 534 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen); 535 return; 536 } 537 538 static void 539 hashIter( 540 HASH_CONTEXT *HASHcontext, 541 unsigned char *HASHdigest, 542 unsigned char *value, 543 int len) 544 { 545 HASH_CONTEXT ctx = *HASHcontext; 546 HASH_Update( &ctx, value, len ); 547 HASH_Final( HASHdigest, &ctx ); 548 } 549 550 /* Index generation function */ 551 int octetStringIndexer( 552 slap_mask_t use, 553 slap_mask_t flags, 554 Syntax *syntax, 555 MatchingRule *mr, 556 struct berval *prefix, 557 BerVarray values, 558 BerVarray *keysp, 559 void *ctx ) 560 { 561 int i; 562 size_t slen, mlen; 563 BerVarray keys; 564 HASH_CONTEXT HASHcontext; 565 unsigned char HASHdigest[HASH_BYTES]; 566 struct berval digest; 567 digest.bv_val = (char *)HASHdigest; 568 digest.bv_len = sizeof(HASHdigest); 569 570 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 571 /* just count them */ 572 } 573 574 /* we should have at least one value at this point */ 575 assert( i > 0 ); 576 577 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 578 579 slen = syntax->ssyn_oidlen; 580 mlen = mr->smr_oidlen; 581 582 hashPreset( &HASHcontext, prefix, 0, syntax, mr); 583 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 584 hashIter( &HASHcontext, HASHdigest, 585 (unsigned char *)values[i].bv_val, values[i].bv_len ); 586 ber_dupbv_x( &keys[i], &digest, ctx ); 587 } 588 589 BER_BVZERO( &keys[i] ); 590 591 *keysp = keys; 592 593 return LDAP_SUCCESS; 594 } 595 596 /* Index generation function */ 597 int octetStringFilter( 598 slap_mask_t use, 599 slap_mask_t flags, 600 Syntax *syntax, 601 MatchingRule *mr, 602 struct berval *prefix, 603 void * assertedValue, 604 BerVarray *keysp, 605 void *ctx ) 606 { 607 size_t slen, mlen; 608 BerVarray keys; 609 HASH_CONTEXT HASHcontext; 610 unsigned char HASHdigest[HASH_BYTES]; 611 struct berval *value = (struct berval *) assertedValue; 612 struct berval digest; 613 digest.bv_val = (char *)HASHdigest; 614 digest.bv_len = sizeof(HASHdigest); 615 616 slen = syntax->ssyn_oidlen; 617 mlen = mr->smr_oidlen; 618 619 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 620 621 hashPreset( &HASHcontext, prefix, 0, syntax, mr ); 622 hashIter( &HASHcontext, HASHdigest, 623 (unsigned char *)value->bv_val, value->bv_len ); 624 625 ber_dupbv_x( keys, &digest, ctx ); 626 BER_BVZERO( &keys[1] ); 627 628 *keysp = keys; 629 630 return LDAP_SUCCESS; 631 } 632 633 static int 634 octetStringSubstringsMatch( 635 int *matchp, 636 slap_mask_t flags, 637 Syntax *syntax, 638 MatchingRule *mr, 639 struct berval *value, 640 void *assertedValue ) 641 { 642 int match = 0; 643 SubstringsAssertion *sub = assertedValue; 644 struct berval left = *value; 645 int i; 646 ber_len_t inlen = 0; 647 648 /* Add up asserted input length */ 649 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 650 inlen += sub->sa_initial.bv_len; 651 } 652 if ( sub->sa_any ) { 653 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 654 inlen += sub->sa_any[i].bv_len; 655 } 656 } 657 if ( !BER_BVISNULL( &sub->sa_final ) ) { 658 inlen += sub->sa_final.bv_len; 659 } 660 661 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 662 if ( inlen > left.bv_len ) { 663 match = 1; 664 goto done; 665 } 666 667 match = memcmp( sub->sa_initial.bv_val, left.bv_val, 668 sub->sa_initial.bv_len ); 669 670 if ( match != 0 ) { 671 goto done; 672 } 673 674 left.bv_val += sub->sa_initial.bv_len; 675 left.bv_len -= sub->sa_initial.bv_len; 676 inlen -= sub->sa_initial.bv_len; 677 } 678 679 if ( !BER_BVISNULL( &sub->sa_final ) ) { 680 if ( inlen > left.bv_len ) { 681 match = 1; 682 goto done; 683 } 684 685 match = memcmp( sub->sa_final.bv_val, 686 &left.bv_val[left.bv_len - sub->sa_final.bv_len], 687 sub->sa_final.bv_len ); 688 689 if ( match != 0 ) { 690 goto done; 691 } 692 693 left.bv_len -= sub->sa_final.bv_len; 694 inlen -= sub->sa_final.bv_len; 695 } 696 697 if ( sub->sa_any ) { 698 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 699 ber_len_t idx; 700 char *p; 701 702 retry: 703 if ( inlen > left.bv_len ) { 704 /* not enough length */ 705 match = 1; 706 goto done; 707 } 708 709 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) { 710 continue; 711 } 712 713 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len ); 714 715 if( p == NULL ) { 716 match = 1; 717 goto done; 718 } 719 720 idx = p - left.bv_val; 721 722 if ( idx >= left.bv_len ) { 723 /* this shouldn't happen */ 724 return LDAP_OTHER; 725 } 726 727 left.bv_val = p; 728 left.bv_len -= idx; 729 730 if ( sub->sa_any[i].bv_len > left.bv_len ) { 731 /* not enough left */ 732 match = 1; 733 goto done; 734 } 735 736 match = memcmp( left.bv_val, 737 sub->sa_any[i].bv_val, 738 sub->sa_any[i].bv_len ); 739 740 if ( match != 0 ) { 741 left.bv_val++; 742 left.bv_len--; 743 goto retry; 744 } 745 746 left.bv_val += sub->sa_any[i].bv_len; 747 left.bv_len -= sub->sa_any[i].bv_len; 748 inlen -= sub->sa_any[i].bv_len; 749 } 750 } 751 752 done: 753 *matchp = match; 754 return LDAP_SUCCESS; 755 } 756 757 /* Substrings Index generation function */ 758 static int 759 octetStringSubstringsIndexer( 760 slap_mask_t use, 761 slap_mask_t flags, 762 Syntax *syntax, 763 MatchingRule *mr, 764 struct berval *prefix, 765 BerVarray values, 766 BerVarray *keysp, 767 void *ctx ) 768 { 769 ber_len_t i, nkeys; 770 size_t slen, mlen; 771 BerVarray keys; 772 773 HASH_CONTEXT HCany, HCini, HCfin; 774 unsigned char HASHdigest[HASH_BYTES]; 775 struct berval digest; 776 digest.bv_val = (char *)HASHdigest; 777 digest.bv_len = sizeof(HASHdigest); 778 779 nkeys = 0; 780 781 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 782 /* count number of indices to generate */ 783 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) { 784 if( values[i].bv_len >= index_substr_if_maxlen ) { 785 nkeys += index_substr_if_maxlen - 786 (index_substr_if_minlen - 1); 787 } else if( values[i].bv_len >= index_substr_if_minlen ) { 788 nkeys += values[i].bv_len - (index_substr_if_minlen - 1); 789 } 790 } 791 792 if( flags & SLAP_INDEX_SUBSTR_ANY ) { 793 if( values[i].bv_len >= index_substr_any_len ) { 794 nkeys += values[i].bv_len - (index_substr_any_len - 1); 795 } 796 } 797 798 if( flags & SLAP_INDEX_SUBSTR_FINAL ) { 799 if( values[i].bv_len >= index_substr_if_maxlen ) { 800 nkeys += index_substr_if_maxlen - 801 (index_substr_if_minlen - 1); 802 } else if( values[i].bv_len >= index_substr_if_minlen ) { 803 nkeys += values[i].bv_len - (index_substr_if_minlen - 1); 804 } 805 } 806 } 807 808 if( nkeys == 0 ) { 809 /* no keys to generate */ 810 *keysp = NULL; 811 return LDAP_SUCCESS; 812 } 813 814 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx ); 815 816 slen = syntax->ssyn_oidlen; 817 mlen = mr->smr_oidlen; 818 819 if ( flags & SLAP_INDEX_SUBSTR_ANY ) 820 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr ); 821 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) 822 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr ); 823 if( flags & SLAP_INDEX_SUBSTR_FINAL ) 824 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr ); 825 826 nkeys = 0; 827 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 828 ber_len_t j,max; 829 830 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) && 831 ( values[i].bv_len >= index_substr_any_len ) ) 832 { 833 max = values[i].bv_len - (index_substr_any_len - 1); 834 835 for( j=0; j<max; j++ ) { 836 hashIter( &HCany, HASHdigest, 837 (unsigned char *)&values[i].bv_val[j], 838 index_substr_any_len ); 839 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 840 } 841 } 842 843 /* skip if too short */ 844 if( values[i].bv_len < index_substr_if_minlen ) continue; 845 846 max = index_substr_if_maxlen < values[i].bv_len 847 ? index_substr_if_maxlen : values[i].bv_len; 848 849 for( j=index_substr_if_minlen; j<=max; j++ ) { 850 851 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) { 852 hashIter( &HCini, HASHdigest, 853 (unsigned char *)values[i].bv_val, j ); 854 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 855 } 856 857 if( flags & SLAP_INDEX_SUBSTR_FINAL ) { 858 hashIter( &HCfin, HASHdigest, 859 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j ); 860 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 861 } 862 863 } 864 } 865 866 if( nkeys > 0 ) { 867 BER_BVZERO( &keys[nkeys] ); 868 *keysp = keys; 869 } else { 870 ch_free( keys ); 871 *keysp = NULL; 872 } 873 874 return LDAP_SUCCESS; 875 } 876 877 static int 878 octetStringSubstringsFilter ( 879 slap_mask_t use, 880 slap_mask_t flags, 881 Syntax *syntax, 882 MatchingRule *mr, 883 struct berval *prefix, 884 void * assertedValue, 885 BerVarray *keysp, 886 void *ctx) 887 { 888 SubstringsAssertion *sa; 889 char pre; 890 ber_len_t nkeys = 0; 891 size_t slen, mlen, klen; 892 BerVarray keys; 893 HASH_CONTEXT HASHcontext; 894 unsigned char HASHdigest[HASH_BYTES]; 895 struct berval *value; 896 struct berval digest; 897 898 sa = (SubstringsAssertion *) assertedValue; 899 900 if( flags & SLAP_INDEX_SUBSTR_INITIAL && 901 !BER_BVISNULL( &sa->sa_initial ) && 902 sa->sa_initial.bv_len >= index_substr_if_minlen ) 903 { 904 nkeys++; 905 if ( sa->sa_initial.bv_len > index_substr_if_maxlen && 906 ( flags & SLAP_INDEX_SUBSTR_ANY )) 907 { 908 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step; 909 } 910 } 911 912 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) { 913 ber_len_t i; 914 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) { 915 if( sa->sa_any[i].bv_len >= index_substr_any_len ) { 916 /* don't bother accounting with stepping */ 917 nkeys += sa->sa_any[i].bv_len - 918 ( index_substr_any_len - 1 ); 919 } 920 } 921 } 922 923 if( flags & SLAP_INDEX_SUBSTR_FINAL && 924 !BER_BVISNULL( &sa->sa_final ) && 925 sa->sa_final.bv_len >= index_substr_if_minlen ) 926 { 927 nkeys++; 928 if ( sa->sa_final.bv_len > index_substr_if_maxlen && 929 ( flags & SLAP_INDEX_SUBSTR_ANY )) 930 { 931 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; 932 } 933 } 934 935 if( nkeys == 0 ) { 936 *keysp = NULL; 937 return LDAP_SUCCESS; 938 } 939 940 digest.bv_val = (char *)HASHdigest; 941 digest.bv_len = sizeof(HASHdigest); 942 943 slen = syntax->ssyn_oidlen; 944 mlen = mr->smr_oidlen; 945 946 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx ); 947 nkeys = 0; 948 949 if( flags & SLAP_INDEX_SUBSTR_INITIAL && 950 !BER_BVISNULL( &sa->sa_initial ) && 951 sa->sa_initial.bv_len >= index_substr_if_minlen ) 952 { 953 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX; 954 value = &sa->sa_initial; 955 956 klen = index_substr_if_maxlen < value->bv_len 957 ? index_substr_if_maxlen : value->bv_len; 958 959 hashPreset( &HASHcontext, prefix, pre, syntax, mr ); 960 hashIter( &HASHcontext, HASHdigest, 961 (unsigned char *)value->bv_val, klen ); 962 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 963 964 /* If initial is too long and we have subany indexed, use it 965 * to match the excess... 966 */ 967 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY)) 968 { 969 ber_len_t j; 970 pre = SLAP_INDEX_SUBSTR_PREFIX; 971 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 972 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step ) 973 { 974 hashIter( &HASHcontext, HASHdigest, 975 (unsigned char *)&value->bv_val[j], index_substr_any_len ); 976 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 977 } 978 } 979 } 980 981 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) { 982 ber_len_t i, j; 983 pre = SLAP_INDEX_SUBSTR_PREFIX; 984 klen = index_substr_any_len; 985 986 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) { 987 if( sa->sa_any[i].bv_len < index_substr_any_len ) { 988 continue; 989 } 990 991 value = &sa->sa_any[i]; 992 993 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 994 for(j=0; 995 j <= value->bv_len - index_substr_any_len; 996 j += index_substr_any_step ) 997 { 998 hashIter( &HASHcontext, HASHdigest, 999 (unsigned char *)&value->bv_val[j], klen ); 1000 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 1001 } 1002 } 1003 } 1004 1005 if( flags & SLAP_INDEX_SUBSTR_FINAL && 1006 !BER_BVISNULL( &sa->sa_final ) && 1007 sa->sa_final.bv_len >= index_substr_if_minlen ) 1008 { 1009 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX; 1010 value = &sa->sa_final; 1011 1012 klen = index_substr_if_maxlen < value->bv_len 1013 ? index_substr_if_maxlen : value->bv_len; 1014 1015 hashPreset( &HASHcontext, prefix, pre, syntax, mr ); 1016 hashIter( &HASHcontext, HASHdigest, 1017 (unsigned char *)&value->bv_val[value->bv_len-klen], klen ); 1018 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 1019 1020 /* If final is too long and we have subany indexed, use it 1021 * to match the excess... 1022 */ 1023 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY)) 1024 { 1025 ber_len_t j; 1026 pre = SLAP_INDEX_SUBSTR_PREFIX; 1027 hashPreset( &HASHcontext, prefix, pre, syntax, mr); 1028 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step ) 1029 { 1030 hashIter( &HASHcontext, HASHdigest, 1031 (unsigned char *)&value->bv_val[j], index_substr_any_len ); 1032 ber_dupbv_x( &keys[nkeys++], &digest, ctx ); 1033 } 1034 } 1035 } 1036 1037 if( nkeys > 0 ) { 1038 BER_BVZERO( &keys[nkeys] ); 1039 *keysp = keys; 1040 } else { 1041 ch_free( keys ); 1042 *keysp = NULL; 1043 } 1044 1045 return LDAP_SUCCESS; 1046 } 1047 1048 static int 1049 bitStringValidate( 1050 Syntax *syntax, 1051 struct berval *in ) 1052 { 1053 ber_len_t i; 1054 1055 /* very unforgiving validation, requires no normalization 1056 * before simplistic matching 1057 */ 1058 if( in->bv_len < 3 ) { 1059 return LDAP_INVALID_SYNTAX; 1060 } 1061 1062 /* RFC 4517 Section 3.3.2 Bit String: 1063 * BitString = SQUOTE *binary-digit SQUOTE "B" 1064 * binary-digit = "0" / "1" 1065 * 1066 * where SQUOTE [RFC4512] is 1067 * SQUOTE = %x27 ; single quote ("'") 1068 * 1069 * Example: '0101111101'B 1070 */ 1071 1072 if( in->bv_val[0] != '\'' || 1073 in->bv_val[in->bv_len - 2] != '\'' || 1074 in->bv_val[in->bv_len - 1] != 'B' ) 1075 { 1076 return LDAP_INVALID_SYNTAX; 1077 } 1078 1079 for( i = in->bv_len - 3; i > 0; i-- ) { 1080 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) { 1081 return LDAP_INVALID_SYNTAX; 1082 } 1083 } 1084 1085 return LDAP_SUCCESS; 1086 } 1087 1088 /* 1089 * Syntaxes from RFC 4517 1090 * 1091 1092 3.3.2. Bit String 1093 1094 A value of the Bit String syntax is a sequence of binary digits. The 1095 LDAP-specific encoding of a value of this syntax is defined by the 1096 following ABNF: 1097 1098 BitString = SQUOTE *binary-digit SQUOTE "B" 1099 1100 binary-digit = "0" / "1" 1101 1102 The <SQUOTE> rule is defined in [MODELS]. 1103 1104 Example: 1105 '0101111101'B 1106 1107 The LDAP definition for the Bit String syntax is: 1108 1109 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) 1110 1111 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1]. 1112 1113 ... 1114 1115 3.3.21. Name and Optional UID 1116 1117 A value of the Name and Optional UID syntax is the distinguished name 1118 [MODELS] of an entity optionally accompanied by a unique identifier 1119 that serves to differentiate the entity from others with an identical 1120 distinguished name. 1121 1122 The LDAP-specific encoding of a value of this syntax is defined by 1123 the following ABNF: 1124 1125 NameAndOptionalUID = distinguishedName [ SHARP BitString ] 1126 1127 The <BitString> rule is defined in Section 3.3.2. The 1128 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is 1129 defined in [MODELS]. 1130 1131 Note that although the '#' character may occur in the string 1132 representation of a distinguished name, no additional escaping of 1133 this character is performed when a <distinguishedName> is encoded in 1134 a <NameAndOptionalUID>. 1135 1136 Example: 1137 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B 1138 1139 The LDAP definition for the Name and Optional UID syntax is: 1140 1141 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' ) 1142 1143 This syntax corresponds to the NameAndOptionalUID ASN.1 type from 1144 [X.520]. 1145 1146 * 1147 * RFC 4512 says: 1148 * 1149 1150 1.4. Common ABNF Productions 1151 1152 ... 1153 SHARP = %x23 ; octothorpe (or sharp sign) ("#") 1154 ... 1155 SQUOTE = %x27 ; single quote ("'") 1156 ... 1157 1158 * 1159 * Note: 1160 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to 1161 * be escaped except when at the beginning of a value, the 1162 * definition of Name and Optional UID appears to be flawed, 1163 * because there is no clear means to determine whether the 1164 * UID part is present or not. 1165 * 1166 * Example: 1167 * 1168 * cn=Someone,dc=example,dc=com#'1'B 1169 * 1170 * could be either a NameAndOptionalUID with trailing UID, i.e. 1171 * 1172 * DN = "cn=Someone,dc=example,dc=com" 1173 * UID = "'1'B" 1174 * 1175 * or a NameAndOptionalUID with no trailing UID, and the AVA 1176 * in the last RDN made of 1177 * 1178 * attributeType = dc 1179 * attributeValue = com#'1'B 1180 * 1181 * in fact "com#'1'B" is a valid IA5 string. 1182 * 1183 * As a consequence, current slapd code takes the presence of 1184 * #<valid BitString> at the end of the string representation 1185 * of a NameAndOptionalUID to mean this is indeed a BitString. 1186 * This is quite arbitrary - it has changed the past and might 1187 * change in the future. 1188 */ 1189 1190 1191 static int 1192 nameUIDValidate( 1193 Syntax *syntax, 1194 struct berval *in ) 1195 { 1196 int rc; 1197 struct berval dn, uid; 1198 1199 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS; 1200 1201 ber_dupbv( &dn, in ); 1202 if( !dn.bv_val ) return LDAP_OTHER; 1203 1204 /* if there's a "#", try bitStringValidate()... */ 1205 uid.bv_val = strrchr( dn.bv_val, '#' ); 1206 if ( !BER_BVISNULL( &uid ) ) { 1207 uid.bv_val++; 1208 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val ); 1209 1210 rc = bitStringValidate( NULL, &uid ); 1211 if ( rc == LDAP_SUCCESS ) { 1212 /* in case of success, trim the UID, 1213 * otherwise treat it as part of the DN */ 1214 dn.bv_len -= uid.bv_len + 1; 1215 uid.bv_val[-1] = '\0'; 1216 } 1217 } 1218 1219 rc = dnValidate( NULL, &dn ); 1220 1221 ber_memfree( dn.bv_val ); 1222 return rc; 1223 } 1224 1225 int 1226 nameUIDPretty( 1227 Syntax *syntax, 1228 struct berval *val, 1229 struct berval *out, 1230 void *ctx ) 1231 { 1232 assert( val != NULL ); 1233 assert( out != NULL ); 1234 1235 1236 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 ); 1237 1238 if( BER_BVISEMPTY( val ) ) { 1239 ber_dupbv_x( out, val, ctx ); 1240 1241 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 1242 return LDAP_INVALID_SYNTAX; 1243 1244 } else { 1245 int rc; 1246 struct berval dnval = *val; 1247 struct berval uidval = BER_BVNULL; 1248 1249 uidval.bv_val = strrchr( val->bv_val, '#' ); 1250 if ( !BER_BVISNULL( &uidval ) ) { 1251 uidval.bv_val++; 1252 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val ); 1253 1254 rc = bitStringValidate( NULL, &uidval ); 1255 1256 if ( rc == LDAP_SUCCESS ) { 1257 ber_dupbv_x( &dnval, val, ctx ); 1258 uidval.bv_val--; 1259 dnval.bv_len -= ++uidval.bv_len; 1260 dnval.bv_val[dnval.bv_len] = '\0'; 1261 1262 } else { 1263 BER_BVZERO( &uidval ); 1264 } 1265 } 1266 1267 rc = dnPretty( syntax, &dnval, out, ctx ); 1268 if ( dnval.bv_val != val->bv_val ) { 1269 slap_sl_free( dnval.bv_val, ctx ); 1270 } 1271 if( rc != LDAP_SUCCESS ) { 1272 return rc; 1273 } 1274 1275 if( !BER_BVISNULL( &uidval ) ) { 1276 char *tmp; 1277 1278 tmp = slap_sl_realloc( out->bv_val, out->bv_len 1279 + uidval.bv_len + 1, 1280 ctx ); 1281 if( tmp == NULL ) { 1282 ber_memfree_x( out->bv_val, ctx ); 1283 return LDAP_OTHER; 1284 } 1285 out->bv_val = tmp; 1286 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len ); 1287 out->bv_len += uidval.bv_len; 1288 out->bv_val[out->bv_len] = '\0'; 1289 } 1290 } 1291 1292 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 ); 1293 1294 return LDAP_SUCCESS; 1295 } 1296 1297 static int 1298 uniqueMemberNormalize( 1299 slap_mask_t usage, 1300 Syntax *syntax, 1301 MatchingRule *mr, 1302 struct berval *val, 1303 struct berval *normalized, 1304 void *ctx ) 1305 { 1306 struct berval out; 1307 int rc; 1308 1309 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 1310 1311 ber_dupbv_x( &out, val, ctx ); 1312 if ( BER_BVISEMPTY( &out ) ) { 1313 *normalized = out; 1314 1315 } else { 1316 struct berval uid = BER_BVNULL; 1317 1318 uid.bv_val = strrchr( out.bv_val, '#' ); 1319 if ( !BER_BVISNULL( &uid ) ) { 1320 uid.bv_val++; 1321 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val ); 1322 1323 rc = bitStringValidate( NULL, &uid ); 1324 if ( rc == LDAP_SUCCESS ) { 1325 uid.bv_val[-1] = '\0'; 1326 out.bv_len -= uid.bv_len + 1; 1327 } else { 1328 BER_BVZERO( &uid ); 1329 } 1330 } 1331 1332 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx ); 1333 1334 if( rc != LDAP_SUCCESS ) { 1335 slap_sl_free( out.bv_val, ctx ); 1336 return LDAP_INVALID_SYNTAX; 1337 } 1338 1339 if( !BER_BVISNULL( &uid ) ) { 1340 char *tmp; 1341 1342 tmp = ch_realloc( normalized->bv_val, 1343 normalized->bv_len + uid.bv_len 1344 + STRLENOF("#") + 1 ); 1345 if ( tmp == NULL ) { 1346 ber_memfree_x( normalized->bv_val, ctx ); 1347 return LDAP_OTHER; 1348 } 1349 1350 normalized->bv_val = tmp; 1351 1352 /* insert the separator */ 1353 normalized->bv_val[normalized->bv_len++] = '#'; 1354 1355 /* append the UID */ 1356 AC_MEMCPY( &normalized->bv_val[normalized->bv_len], 1357 uid.bv_val, uid.bv_len ); 1358 normalized->bv_len += uid.bv_len; 1359 1360 /* terminate */ 1361 normalized->bv_val[normalized->bv_len] = '\0'; 1362 } 1363 1364 slap_sl_free( out.bv_val, ctx ); 1365 } 1366 1367 return LDAP_SUCCESS; 1368 } 1369 1370 static int 1371 uniqueMemberMatch( 1372 int *matchp, 1373 slap_mask_t flags, 1374 Syntax *syntax, 1375 MatchingRule *mr, 1376 struct berval *value, 1377 void *assertedValue ) 1378 { 1379 int match; 1380 struct berval *asserted = (struct berval *) assertedValue; 1381 struct berval assertedDN = *asserted; 1382 struct berval assertedUID = BER_BVNULL; 1383 struct berval valueDN = *value; 1384 struct berval valueUID = BER_BVNULL; 1385 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX); 1386 1387 if ( !BER_BVISEMPTY( asserted ) ) { 1388 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1389 if ( !BER_BVISNULL( &assertedUID ) ) { 1390 assertedUID.bv_val++; 1391 assertedUID.bv_len = assertedDN.bv_len 1392 - ( assertedUID.bv_val - assertedDN.bv_val ); 1393 1394 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1395 assertedDN.bv_len -= assertedUID.bv_len + 1; 1396 1397 } else { 1398 BER_BVZERO( &assertedUID ); 1399 } 1400 } 1401 } 1402 1403 if ( !BER_BVISEMPTY( value ) ) { 1404 1405 valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); 1406 if ( !BER_BVISNULL( &valueUID ) ) { 1407 valueUID.bv_val++; 1408 valueUID.bv_len = valueDN.bv_len 1409 - ( valueUID.bv_val - valueDN.bv_val ); 1410 1411 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) { 1412 valueDN.bv_len -= valueUID.bv_len + 1; 1413 1414 } else { 1415 BER_BVZERO( &valueUID ); 1416 } 1417 } 1418 } 1419 1420 if( valueUID.bv_len && assertedUID.bv_len ) { 1421 match = valueUID.bv_len - assertedUID.bv_len; 1422 if ( match ) { 1423 *matchp = match; 1424 return LDAP_SUCCESS; 1425 } 1426 1427 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len ); 1428 if( match ) { 1429 *matchp = match; 1430 return LDAP_SUCCESS; 1431 } 1432 1433 } else if ( !approx && valueUID.bv_len ) { 1434 match = -1; 1435 *matchp = match; 1436 return LDAP_SUCCESS; 1437 1438 } else if ( !approx && assertedUID.bv_len ) { 1439 match = 1; 1440 *matchp = match; 1441 return LDAP_SUCCESS; 1442 } 1443 1444 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN ); 1445 } 1446 1447 static int 1448 uniqueMemberIndexer( 1449 slap_mask_t use, 1450 slap_mask_t flags, 1451 Syntax *syntax, 1452 MatchingRule *mr, 1453 struct berval *prefix, 1454 BerVarray values, 1455 BerVarray *keysp, 1456 void *ctx ) 1457 { 1458 BerVarray dnvalues; 1459 int rc; 1460 int i; 1461 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 1462 /* just count them */ 1463 } 1464 assert( i > 0 ); 1465 1466 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 1467 1468 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 1469 struct berval assertedDN = values[i]; 1470 struct berval assertedUID = BER_BVNULL; 1471 1472 if ( !BER_BVISEMPTY( &assertedDN ) ) { 1473 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1474 if ( !BER_BVISNULL( &assertedUID ) ) { 1475 assertedUID.bv_val++; 1476 assertedUID.bv_len = assertedDN.bv_len 1477 - ( assertedUID.bv_val - assertedDN.bv_val ); 1478 1479 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1480 assertedDN.bv_len -= assertedUID.bv_len + 1; 1481 1482 } else { 1483 BER_BVZERO( &assertedUID ); 1484 } 1485 } 1486 } 1487 1488 dnvalues[i] = assertedDN; 1489 } 1490 BER_BVZERO( &dnvalues[i] ); 1491 1492 rc = octetStringIndexer( use, flags, syntax, mr, prefix, 1493 dnvalues, keysp, ctx ); 1494 1495 slap_sl_free( dnvalues, ctx ); 1496 return rc; 1497 } 1498 1499 static int 1500 uniqueMemberFilter( 1501 slap_mask_t use, 1502 slap_mask_t flags, 1503 Syntax *syntax, 1504 MatchingRule *mr, 1505 struct berval *prefix, 1506 void * assertedValue, 1507 BerVarray *keysp, 1508 void *ctx ) 1509 { 1510 struct berval *asserted = (struct berval *) assertedValue; 1511 struct berval assertedDN = *asserted; 1512 struct berval assertedUID = BER_BVNULL; 1513 1514 if ( !BER_BVISEMPTY( asserted ) ) { 1515 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); 1516 if ( !BER_BVISNULL( &assertedUID ) ) { 1517 assertedUID.bv_val++; 1518 assertedUID.bv_len = assertedDN.bv_len 1519 - ( assertedUID.bv_val - assertedDN.bv_val ); 1520 1521 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) { 1522 assertedDN.bv_len -= assertedUID.bv_len + 1; 1523 1524 } else { 1525 BER_BVZERO( &assertedUID ); 1526 } 1527 } 1528 } 1529 1530 return octetStringFilter( use, flags, syntax, mr, prefix, 1531 &assertedDN, keysp, ctx ); 1532 } 1533 1534 1535 /* 1536 * Handling boolean syntax and matching is quite rigid. 1537 * A more flexible approach would be to allow a variety 1538 * of strings to be normalized and prettied into TRUE 1539 * and FALSE. 1540 */ 1541 static int 1542 booleanValidate( 1543 Syntax *syntax, 1544 struct berval *in ) 1545 { 1546 /* very unforgiving validation, requires no normalization 1547 * before simplistic matching 1548 */ 1549 1550 if( in->bv_len == 4 ) { 1551 if( bvmatch( in, &slap_true_bv ) ) { 1552 return LDAP_SUCCESS; 1553 } 1554 } else if( in->bv_len == 5 ) { 1555 if( bvmatch( in, &slap_false_bv ) ) { 1556 return LDAP_SUCCESS; 1557 } 1558 } 1559 1560 return LDAP_INVALID_SYNTAX; 1561 } 1562 1563 static int 1564 booleanMatch( 1565 int *matchp, 1566 slap_mask_t flags, 1567 Syntax *syntax, 1568 MatchingRule *mr, 1569 struct berval *value, 1570 void *assertedValue ) 1571 { 1572 /* simplistic matching allowed by rigid validation */ 1573 struct berval *asserted = (struct berval *) assertedValue; 1574 *matchp = value->bv_len != asserted->bv_len; 1575 return LDAP_SUCCESS; 1576 } 1577 1578 /*------------------------------------------------------------------- 1579 LDAP/X.500 string syntax / matching rules have a few oddities. This 1580 comment attempts to detail how slapd(8) treats them. 1581 1582 Summary: 1583 StringSyntax X.500 LDAP Matching/Comments 1584 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces 1585 PrintableString subset subset i/e + ignore insignificant spaces 1586 PrintableString subset subset i/e + ignore insignificant spaces 1587 NumericString subset subset ignore all spaces 1588 IA5String ASCII ASCII i/e + ignore insignificant spaces 1589 TeletexString T.61 T.61 i/e + ignore insignificant spaces 1590 1591 TelephoneNumber subset subset i + ignore all spaces and "-" 1592 1593 See RFC 4518 for details. 1594 1595 1596 Directory String - 1597 In X.500(93), a directory string can be either a PrintableString, 1598 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)). 1599 In later versions, more CHOICEs were added. In all cases the string 1600 must be non-empty. 1601 1602 In LDAPv3, a directory string is a UTF-8 encoded UCS string. 1603 A directory string cannot be zero length. 1604 1605 For matching, there are both case ignore and exact rules. Both 1606 also require that "insignificant" spaces be ignored. 1607 spaces before the first non-space are ignored; 1608 spaces after the last non-space are ignored; 1609 spaces after a space are ignored. 1610 Note: by these rules (and as clarified in X.520), a string of only 1611 spaces is to be treated as if held one space, not empty (which 1612 would be a syntax error). 1613 1614 NumericString 1615 In ASN.1, numeric string is just a string of digits and spaces 1616 and could be empty. However, in X.500, all attribute values of 1617 numeric string carry a non-empty constraint. For example: 1618 1619 internationalISDNNumber ATTRIBUTE ::= { 1620 WITH SYNTAX InternationalISDNNumber 1621 EQUALITY MATCHING RULE numericStringMatch 1622 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch 1623 ID id-at-internationalISDNNumber } 1624 InternationalISDNNumber ::= 1625 NumericString (SIZE(1..ub-international-isdn-number)) 1626 1627 Unforunately, some assertion values are don't carry the same 1628 constraint (but its unclear how such an assertion could ever 1629 be true). In LDAP, there is one syntax (numericString) not two 1630 (numericString with constraint, numericString without constraint). 1631 This should be treated as numericString with non-empty constraint. 1632 Note that while someone may have no ISDN number, there are no ISDN 1633 numbers which are zero length. 1634 1635 In matching, spaces are ignored. 1636 1637 PrintableString 1638 In ASN.1, Printable string is just a string of printable characters 1639 and can be empty. In X.500, semantics much like NumericString (see 1640 serialNumber for a like example) excepting uses insignificant space 1641 handling instead of ignore all spaces. They must be non-empty. 1642 1643 IA5String 1644 Basically same as PrintableString. There are no examples in X.500, 1645 but same logic applies. Empty strings are allowed. 1646 1647 -------------------------------------------------------------------*/ 1648 1649 static int 1650 UTF8StringValidate( 1651 Syntax *syntax, 1652 struct berval *in ) 1653 { 1654 ber_len_t count; 1655 int len; 1656 unsigned char *u = (unsigned char *)in->bv_val; 1657 1658 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) { 1659 /* directory strings cannot be empty */ 1660 return LDAP_INVALID_SYNTAX; 1661 } 1662 1663 for( count = in->bv_len; count > 0; count -= len, u += len ) { 1664 /* get the length indicated by the first byte */ 1665 len = LDAP_UTF8_CHARLEN2( u, len ); 1666 1667 /* very basic checks */ 1668 switch( len ) { 1669 case 6: 1670 if( (u[5] & 0xC0) != 0x80 ) { 1671 return LDAP_INVALID_SYNTAX; 1672 } 1673 case 5: 1674 if( (u[4] & 0xC0) != 0x80 ) { 1675 return LDAP_INVALID_SYNTAX; 1676 } 1677 case 4: 1678 if( (u[3] & 0xC0) != 0x80 ) { 1679 return LDAP_INVALID_SYNTAX; 1680 } 1681 case 3: 1682 if( (u[2] & 0xC0 )!= 0x80 ) { 1683 return LDAP_INVALID_SYNTAX; 1684 } 1685 case 2: 1686 if( (u[1] & 0xC0) != 0x80 ) { 1687 return LDAP_INVALID_SYNTAX; 1688 } 1689 case 1: 1690 /* CHARLEN already validated it */ 1691 break; 1692 default: 1693 return LDAP_INVALID_SYNTAX; 1694 } 1695 1696 /* make sure len corresponds with the offset 1697 to the next character */ 1698 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX; 1699 } 1700 1701 if( count != 0 ) { 1702 return LDAP_INVALID_SYNTAX; 1703 } 1704 1705 return LDAP_SUCCESS; 1706 } 1707 1708 static int 1709 UTF8StringNormalize( 1710 slap_mask_t use, 1711 Syntax *syntax, 1712 MatchingRule *mr, 1713 struct berval *val, 1714 struct berval *normalized, 1715 void *ctx ) 1716 { 1717 struct berval tmp, nvalue; 1718 int flags, wasspace; 1719 ber_len_t i; 1720 1721 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 1722 1723 if( BER_BVISNULL( val ) ) { 1724 /* assume we're dealing with a syntax (e.g., UTF8String) 1725 * which allows empty strings 1726 */ 1727 BER_BVZERO( normalized ); 1728 return LDAP_SUCCESS; 1729 } 1730 1731 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch ) 1732 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD; 1733 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX ) 1734 ? LDAP_UTF8_APPROX : 0; 1735 1736 val = UTF8bvnormalize( val, &tmp, flags, ctx ); 1737 if( val == NULL ) { 1738 return LDAP_OTHER; 1739 } 1740 1741 /* collapse spaces (in place) */ 1742 nvalue.bv_len = 0; 1743 nvalue.bv_val = tmp.bv_val; 1744 1745 /* trim leading spaces? */ 1746 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) || 1747 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL )); 1748 1749 for( i = 0; i < tmp.bv_len; i++) { 1750 if ( ASCII_SPACE( tmp.bv_val[i] )) { 1751 if( wasspace++ == 0 ) { 1752 /* trim repeated spaces */ 1753 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i]; 1754 } 1755 } else { 1756 wasspace = 0; 1757 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i]; 1758 } 1759 } 1760 1761 if( !BER_BVISEMPTY( &nvalue ) ) { 1762 /* trim trailing space? */ 1763 if( wasspace && ( 1764 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) && 1765 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY )) 1766 { 1767 --nvalue.bv_len; 1768 } 1769 nvalue.bv_val[nvalue.bv_len] = '\0'; 1770 1771 } else { 1772 /* string of all spaces is treated as one space */ 1773 nvalue.bv_val[0] = ' '; 1774 nvalue.bv_val[1] = '\0'; 1775 nvalue.bv_len = 1; 1776 } 1777 1778 *normalized = nvalue; 1779 return LDAP_SUCCESS; 1780 } 1781 1782 static int 1783 directoryStringSubstringsMatch( 1784 int *matchp, 1785 slap_mask_t flags, 1786 Syntax *syntax, 1787 MatchingRule *mr, 1788 struct berval *value, 1789 void *assertedValue ) 1790 { 1791 int match = 0; 1792 SubstringsAssertion *sub = assertedValue; 1793 struct berval left = *value; 1794 ber_len_t i; 1795 int priorspace=0; 1796 1797 if ( !BER_BVISNULL( &sub->sa_initial ) ) { 1798 if ( sub->sa_initial.bv_len > left.bv_len ) { 1799 /* not enough left */ 1800 match = 1; 1801 goto done; 1802 } 1803 1804 match = memcmp( sub->sa_initial.bv_val, left.bv_val, 1805 sub->sa_initial.bv_len ); 1806 1807 if ( match != 0 ) { 1808 goto done; 1809 } 1810 1811 left.bv_val += sub->sa_initial.bv_len; 1812 left.bv_len -= sub->sa_initial.bv_len; 1813 1814 priorspace = ASCII_SPACE( 1815 sub->sa_initial.bv_val[sub->sa_initial.bv_len] ); 1816 } 1817 1818 if ( sub->sa_any ) { 1819 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { 1820 ber_len_t idx; 1821 char *p; 1822 1823 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] ) 1824 && ASCII_SPACE( sub->sa_any[i].bv_val[0] )) 1825 { 1826 /* allow next space to match */ 1827 left.bv_val--; 1828 left.bv_len++; 1829 } 1830 priorspace=0; 1831 1832 retry: 1833 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) { 1834 continue; 1835 } 1836 1837 if ( sub->sa_any[i].bv_len > left.bv_len ) { 1838 /* not enough left */ 1839 match = 1; 1840 goto done; 1841 } 1842 1843 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len ); 1844 1845 if( p == NULL ) { 1846 match = 1; 1847 goto done; 1848 } 1849 1850 idx = p - left.bv_val; 1851 1852 if ( idx >= left.bv_len ) { 1853 /* this shouldn't happen */ 1854 return LDAP_OTHER; 1855 } 1856 1857 left.bv_val = p; 1858 left.bv_len -= idx; 1859 1860 if ( sub->sa_any[i].bv_len > left.bv_len ) { 1861 /* not enough left */ 1862 match = 1; 1863 goto done; 1864 } 1865 1866 match = memcmp( left.bv_val, 1867 sub->sa_any[i].bv_val, 1868 sub->sa_any[i].bv_len ); 1869 1870 if ( match != 0 ) { 1871 left.bv_val++; 1872 left.bv_len--; 1873 goto retry; 1874 } 1875 1876 left.bv_val += sub->sa_any[i].bv_len; 1877 left.bv_len -= sub->sa_any[i].bv_len; 1878 1879 priorspace = ASCII_SPACE( 1880 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] ); 1881 } 1882 } 1883 1884 if ( !BER_BVISNULL( &sub->sa_final ) ) { 1885 if( priorspace && !BER_BVISEMPTY( &sub->sa_final ) 1886 && ASCII_SPACE( sub->sa_final.bv_val[0] )) 1887 { 1888 /* allow next space to match */ 1889 left.bv_val--; 1890 left.bv_len++; 1891 } 1892 1893 if ( sub->sa_final.bv_len > left.bv_len ) { 1894 /* not enough left */ 1895 match = 1; 1896 goto done; 1897 } 1898 1899 match = memcmp( sub->sa_final.bv_val, 1900 &left.bv_val[left.bv_len - sub->sa_final.bv_len], 1901 sub->sa_final.bv_len ); 1902 1903 if ( match != 0 ) { 1904 goto done; 1905 } 1906 } 1907 1908 done: 1909 *matchp = match; 1910 return LDAP_SUCCESS; 1911 } 1912 1913 #if defined(SLAPD_APPROX_INITIALS) 1914 # define SLAPD_APPROX_DELIMITER "._ " 1915 # define SLAPD_APPROX_WORDLEN 2 1916 #else 1917 # define SLAPD_APPROX_DELIMITER " " 1918 # define SLAPD_APPROX_WORDLEN 1 1919 #endif 1920 1921 static int 1922 approxMatch( 1923 int *matchp, 1924 slap_mask_t flags, 1925 Syntax *syntax, 1926 MatchingRule *mr, 1927 struct berval *value, 1928 void *assertedValue ) 1929 { 1930 struct berval *nval, *assertv; 1931 char *val, **values, **words, *c; 1932 int i, count, len, nextchunk=0, nextavail=0; 1933 1934 /* Yes, this is necessary */ 1935 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL ); 1936 if( nval == NULL ) { 1937 *matchp = 1; 1938 return LDAP_SUCCESS; 1939 } 1940 1941 /* Yes, this is necessary */ 1942 assertv = UTF8bvnormalize( ((struct berval *)assertedValue), 1943 NULL, LDAP_UTF8_APPROX, NULL ); 1944 if( assertv == NULL ) { 1945 ber_bvfree( nval ); 1946 *matchp = 1; 1947 return LDAP_SUCCESS; 1948 } 1949 1950 /* Isolate how many words there are */ 1951 for ( c = nval->bv_val, count = 1; *c; c++ ) { 1952 c = strpbrk( c, SLAPD_APPROX_DELIMITER ); 1953 if ( c == NULL ) break; 1954 *c = '\0'; 1955 count++; 1956 } 1957 1958 /* Get a phonetic copy of each word */ 1959 words = (char **)ch_malloc( count * sizeof(char *) ); 1960 values = (char **)ch_malloc( count * sizeof(char *) ); 1961 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) { 1962 words[i] = c; 1963 values[i] = phonetic(c); 1964 } 1965 1966 /* Work through the asserted value's words, to see if at least some 1967 * of the words are there, in the same order. */ 1968 len = 0; 1969 while ( (ber_len_t) nextchunk < assertv->bv_len ) { 1970 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER); 1971 if( len == 0 ) { 1972 nextchunk++; 1973 continue; 1974 } 1975 #if defined(SLAPD_APPROX_INITIALS) 1976 else if( len == 1 ) { 1977 /* Single letter words need to at least match one word's initial */ 1978 for( i=nextavail; i<count; i++ ) 1979 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) { 1980 nextavail=i+1; 1981 break; 1982 } 1983 } 1984 #endif 1985 else { 1986 /* Isolate the next word in the asserted value and phonetic it */ 1987 assertv->bv_val[nextchunk+len] = '\0'; 1988 val = phonetic( assertv->bv_val + nextchunk ); 1989 1990 /* See if this phonetic chunk is in the remaining words of *value */ 1991 for( i=nextavail; i<count; i++ ){ 1992 if( !strcmp( val, values[i] ) ){ 1993 nextavail = i+1; 1994 break; 1995 } 1996 } 1997 ch_free( val ); 1998 } 1999 2000 /* This chunk in the asserted value was NOT within the *value. */ 2001 if( i >= count ) { 2002 nextavail=-1; 2003 break; 2004 } 2005 2006 /* Go on to the next word in the asserted value */ 2007 nextchunk += len+1; 2008 } 2009 2010 /* If some of the words were seen, call it a match */ 2011 if( nextavail > 0 ) { 2012 *matchp = 0; 2013 } 2014 else { 2015 *matchp = 1; 2016 } 2017 2018 /* Cleanup allocs */ 2019 ber_bvfree( assertv ); 2020 for( i=0; i<count; i++ ) { 2021 ch_free( values[i] ); 2022 } 2023 ch_free( values ); 2024 ch_free( words ); 2025 ber_bvfree( nval ); 2026 2027 return LDAP_SUCCESS; 2028 } 2029 2030 static int 2031 approxIndexer( 2032 slap_mask_t use, 2033 slap_mask_t flags, 2034 Syntax *syntax, 2035 MatchingRule *mr, 2036 struct berval *prefix, 2037 BerVarray values, 2038 BerVarray *keysp, 2039 void *ctx ) 2040 { 2041 char *c; 2042 int i,j, len, wordcount, keycount=0; 2043 struct berval *newkeys; 2044 BerVarray keys=NULL; 2045 2046 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) { 2047 struct berval val = BER_BVNULL; 2048 /* Yes, this is necessary */ 2049 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL ); 2050 assert( !BER_BVISNULL( &val ) ); 2051 2052 /* Isolate how many words there are. There will be a key for each */ 2053 for( wordcount = 0, c = val.bv_val; *c; c++) { 2054 len = strcspn(c, SLAPD_APPROX_DELIMITER); 2055 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++; 2056 c+= len; 2057 if (*c == '\0') break; 2058 *c = '\0'; 2059 } 2060 2061 /* Allocate/increase storage to account for new keys */ 2062 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1) 2063 * sizeof(struct berval) ); 2064 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) ); 2065 if( keys ) ch_free( keys ); 2066 keys = newkeys; 2067 2068 /* Get a phonetic copy of each word */ 2069 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) { 2070 len = strlen( c ); 2071 if( len < SLAPD_APPROX_WORDLEN ) continue; 2072 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] ); 2073 keycount++; 2074 i++; 2075 } 2076 2077 ber_memfree( val.bv_val ); 2078 } 2079 BER_BVZERO( &keys[keycount] ); 2080 *keysp = keys; 2081 2082 return LDAP_SUCCESS; 2083 } 2084 2085 static int 2086 approxFilter( 2087 slap_mask_t use, 2088 slap_mask_t flags, 2089 Syntax *syntax, 2090 MatchingRule *mr, 2091 struct berval *prefix, 2092 void * assertedValue, 2093 BerVarray *keysp, 2094 void *ctx ) 2095 { 2096 char *c; 2097 int i, count, len; 2098 struct berval *val; 2099 BerVarray keys; 2100 2101 /* Yes, this is necessary */ 2102 val = UTF8bvnormalize( ((struct berval *)assertedValue), 2103 NULL, LDAP_UTF8_APPROX, NULL ); 2104 if( val == NULL || BER_BVISNULL( val ) ) { 2105 keys = (struct berval *)ch_malloc( sizeof(struct berval) ); 2106 BER_BVZERO( &keys[0] ); 2107 *keysp = keys; 2108 ber_bvfree( val ); 2109 return LDAP_SUCCESS; 2110 } 2111 2112 /* Isolate how many words there are. There will be a key for each */ 2113 for( count = 0,c = val->bv_val; *c; c++) { 2114 len = strcspn(c, SLAPD_APPROX_DELIMITER); 2115 if( len >= SLAPD_APPROX_WORDLEN ) count++; 2116 c+= len; 2117 if (*c == '\0') break; 2118 *c = '\0'; 2119 } 2120 2121 /* Allocate storage for new keys */ 2122 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) ); 2123 2124 /* Get a phonetic copy of each word */ 2125 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) { 2126 len = strlen(c); 2127 if( len < SLAPD_APPROX_WORDLEN ) continue; 2128 ber_str2bv( phonetic( c ), 0, 0, &keys[i] ); 2129 i++; 2130 } 2131 2132 ber_bvfree( val ); 2133 2134 BER_BVZERO( &keys[count] ); 2135 *keysp = keys; 2136 2137 return LDAP_SUCCESS; 2138 } 2139 2140 /* Remove all spaces and '-' characters */ 2141 static int 2142 telephoneNumberNormalize( 2143 slap_mask_t usage, 2144 Syntax *syntax, 2145 MatchingRule *mr, 2146 struct berval *val, 2147 struct berval *normalized, 2148 void *ctx ) 2149 { 2150 char *p, *q; 2151 2152 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 2153 2154 /* validator should have refused an empty string */ 2155 assert( !BER_BVISEMPTY( val ) ); 2156 2157 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 2158 2159 for( p = val->bv_val; *p; p++ ) { 2160 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) { 2161 *q++ = *p; 2162 } 2163 } 2164 *q = '\0'; 2165 2166 normalized->bv_len = q - normalized->bv_val; 2167 2168 if( BER_BVISEMPTY( normalized ) ) { 2169 slap_sl_free( normalized->bv_val, ctx ); 2170 BER_BVZERO( normalized ); 2171 return LDAP_INVALID_SYNTAX; 2172 } 2173 2174 return LDAP_SUCCESS; 2175 } 2176 2177 static int 2178 postalAddressValidate( 2179 Syntax *syntax, 2180 struct berval *in ) 2181 { 2182 struct berval bv = *in; 2183 ber_len_t c; 2184 2185 for ( c = 0; c < in->bv_len; c++ ) { 2186 if ( in->bv_val[c] == '\\' ) { 2187 c++; 2188 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0 2189 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 ) 2190 { 2191 return LDAP_INVALID_SYNTAX; 2192 } 2193 continue; 2194 } 2195 2196 if ( in->bv_val[c] == '$' ) { 2197 bv.bv_len = &in->bv_val[c] - bv.bv_val; 2198 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) { 2199 return LDAP_INVALID_SYNTAX; 2200 } 2201 bv.bv_val = &in->bv_val[c] + 1; 2202 } 2203 } 2204 2205 bv.bv_len = &in->bv_val[c] - bv.bv_val; 2206 return UTF8StringValidate( NULL, &bv ); 2207 } 2208 2209 static int 2210 postalAddressNormalize( 2211 slap_mask_t usage, 2212 Syntax *syntax, 2213 MatchingRule *mr, 2214 struct berval *val, 2215 struct berval *normalized, 2216 void *ctx ) 2217 { 2218 BerVarray lines = NULL, nlines = NULL; 2219 ber_len_t l, c; 2220 int rc = LDAP_SUCCESS; 2221 MatchingRule *xmr = NULL; 2222 char *p; 2223 2224 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) { 2225 xmr = slap_schema.si_mr_caseIgnoreMatch; 2226 2227 } else { 2228 xmr = slap_schema.si_mr_caseExactMatch; 2229 } 2230 2231 for ( l = 0, c = 0; c < val->bv_len; c++ ) { 2232 if ( val->bv_val[c] == '$' ) { 2233 l++; 2234 } 2235 } 2236 2237 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx ); 2238 nlines = &lines[l + 2]; 2239 2240 lines[0].bv_val = val->bv_val; 2241 for ( l = 0, c = 0; c < val->bv_len; c++ ) { 2242 if ( val->bv_val[c] == '$' ) { 2243 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val; 2244 l++; 2245 lines[l].bv_val = &val->bv_val[c + 1]; 2246 } 2247 } 2248 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val; 2249 2250 normalized->bv_len = l; 2251 2252 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) { 2253 /* NOTE: we directly normalize each line, 2254 * without unescaping the values, since the special 2255 * values '\24' ('$') and '\5C' ('\') are not affected 2256 * by normalization */ 2257 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx ); 2258 if ( rc != LDAP_SUCCESS ) { 2259 rc = LDAP_INVALID_SYNTAX; 2260 goto done; 2261 } 2262 2263 normalized->bv_len += nlines[l].bv_len; 2264 } 2265 2266 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2267 2268 p = normalized->bv_val; 2269 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) { 2270 p = lutil_strbvcopy( p, &nlines[l] ); 2271 *p++ = '$'; 2272 } 2273 *--p = '\0'; 2274 2275 assert( p == &normalized->bv_val[normalized->bv_len] ); 2276 2277 done:; 2278 if ( nlines != NULL ) { 2279 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) { 2280 slap_sl_free( nlines[l].bv_val, ctx ); 2281 } 2282 2283 slap_sl_free( lines, ctx ); 2284 } 2285 2286 return rc; 2287 } 2288 2289 int 2290 numericoidValidate( 2291 Syntax *syntax, 2292 struct berval *in ) 2293 { 2294 struct berval val = *in; 2295 2296 if( BER_BVISEMPTY( &val ) ) { 2297 /* disallow empty strings */ 2298 return LDAP_INVALID_SYNTAX; 2299 } 2300 2301 while( OID_LEADCHAR( val.bv_val[0] ) ) { 2302 if ( val.bv_len == 1 ) { 2303 return LDAP_SUCCESS; 2304 } 2305 2306 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) { 2307 break; 2308 } 2309 2310 val.bv_val++; 2311 val.bv_len--; 2312 2313 while ( OID_LEADCHAR( val.bv_val[0] )) { 2314 val.bv_val++; 2315 val.bv_len--; 2316 2317 if ( val.bv_len == 0 ) { 2318 return LDAP_SUCCESS; 2319 } 2320 } 2321 2322 if( !OID_SEPARATOR( val.bv_val[0] )) { 2323 break; 2324 } 2325 2326 val.bv_val++; 2327 val.bv_len--; 2328 } 2329 2330 return LDAP_INVALID_SYNTAX; 2331 } 2332 2333 static int 2334 integerValidate( 2335 Syntax *syntax, 2336 struct berval *in ) 2337 { 2338 ber_len_t i; 2339 struct berval val = *in; 2340 2341 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX; 2342 2343 if ( val.bv_val[0] == '-' ) { 2344 val.bv_len--; 2345 val.bv_val++; 2346 2347 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */ 2348 return LDAP_INVALID_SYNTAX; 2349 } 2350 2351 if( val.bv_val[0] == '0' ) { /* "-0" */ 2352 return LDAP_INVALID_SYNTAX; 2353 } 2354 2355 } else if ( val.bv_val[0] == '0' ) { 2356 if( val.bv_len > 1 ) { /* "0<more>" */ 2357 return LDAP_INVALID_SYNTAX; 2358 } 2359 2360 return LDAP_SUCCESS; 2361 } 2362 2363 for( i=0; i < val.bv_len; i++ ) { 2364 if( !ASCII_DIGIT(val.bv_val[i]) ) { 2365 return LDAP_INVALID_SYNTAX; 2366 } 2367 } 2368 2369 return LDAP_SUCCESS; 2370 } 2371 2372 static int 2373 integerMatch( 2374 int *matchp, 2375 slap_mask_t flags, 2376 Syntax *syntax, 2377 MatchingRule *mr, 2378 struct berval *value, 2379 void *assertedValue ) 2380 { 2381 struct berval *asserted = (struct berval *) assertedValue; 2382 int vsign = 1, asign = 1; /* default sign = '+' */ 2383 struct berval v, a; 2384 int match; 2385 2386 v = *value; 2387 if( v.bv_val[0] == '-' ) { 2388 vsign = -1; 2389 v.bv_val++; 2390 v.bv_len--; 2391 } 2392 2393 if( BER_BVISEMPTY( &v ) ) vsign = 0; 2394 2395 a = *asserted; 2396 if( a.bv_val[0] == '-' ) { 2397 asign = -1; 2398 a.bv_val++; 2399 a.bv_len--; 2400 } 2401 2402 if( BER_BVISEMPTY( &a ) ) vsign = 0; 2403 2404 match = vsign - asign; 2405 if( match == 0 ) { 2406 match = ( v.bv_len != a.bv_len 2407 ? ( v.bv_len < a.bv_len ? -1 : 1 ) 2408 : memcmp( v.bv_val, a.bv_val, v.bv_len )); 2409 if( vsign < 0 ) match = -match; 2410 } 2411 2412 *matchp = match; 2413 return LDAP_SUCCESS; 2414 } 2415 2416 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */ 2417 #define INDEX_INTLEN_CHOP 7 2418 #define INDEX_INTLEN_CHOPBYTES 3 2419 2420 static int 2421 integerVal2Key( 2422 struct berval *in, 2423 struct berval *key, 2424 struct berval *tmp, 2425 void *ctx ) 2426 { 2427 /* index format: 2428 * only if too large: one's complement <sign*exponent (chopped bytes)>, 2429 * two's complement value (sign-extended or chopped as needed), 2430 * however the top <number of exponent-bytes + 1> bits of first byte 2431 * above is the inverse sign. The next bit is the sign as delimiter. 2432 */ 2433 ber_slen_t k = index_intlen_strlen; 2434 ber_len_t chop = 0; 2435 unsigned signmask = ~0x7fU; 2436 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff; 2437 struct berval val = *in, itmp = *tmp; 2438 2439 if ( val.bv_val[0] != '-' ) { 2440 neg = 0; 2441 --k; 2442 } 2443 2444 /* Chop least significant digits, increase length instead */ 2445 if ( val.bv_len > (ber_len_t) k ) { 2446 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */ 2447 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */ 2448 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */ 2449 } 2450 2451 if ( lutil_str2bin( &val, &itmp, ctx )) { 2452 return LDAP_INVALID_SYNTAX; 2453 } 2454 2455 /* Omit leading sign byte */ 2456 if ( itmp.bv_val[0] == neg ) { 2457 itmp.bv_val++; 2458 itmp.bv_len--; 2459 } 2460 2461 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop); 2462 if ( k > 0 ) { 2463 assert( chop == 0 ); 2464 memset( key->bv_val, neg, k ); /* sign-extend */ 2465 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) { 2466 lenp = lenbuf + sizeof(lenbuf); 2467 chop = - (ber_len_t) k; 2468 do { 2469 *--lenp = ((unsigned char) chop & 0xff) ^ neg; 2470 signmask >>= 1; 2471 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) ); 2472 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff) 2473 * are 1, and the top n+2 bits of lenp[] are the sign bit. */ 2474 k = (lenbuf + sizeof(lenbuf)) - lenp; 2475 if ( k > (ber_slen_t) index_intlen ) 2476 k = index_intlen; 2477 memcpy( key->bv_val, lenp, k ); 2478 itmp.bv_len = index_intlen - k; 2479 } 2480 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len ); 2481 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */ 2482 return 0; 2483 } 2484 2485 /* Index generation function */ 2486 static int 2487 integerIndexer( 2488 slap_mask_t use, 2489 slap_mask_t flags, 2490 Syntax *syntax, 2491 MatchingRule *mr, 2492 struct berval *prefix, 2493 BerVarray values, 2494 BerVarray *keysp, 2495 void *ctx ) 2496 { 2497 char ibuf[64]; 2498 struct berval itmp; 2499 BerVarray keys; 2500 ber_len_t vlen; 2501 int i, rc; 2502 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2503 2504 /* count the values and find max needed length */ 2505 vlen = 0; 2506 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2507 if ( vlen < values[i].bv_len ) 2508 vlen = values[i].bv_len; 2509 } 2510 if ( vlen > maxstrlen ) 2511 vlen = maxstrlen; 2512 2513 /* we should have at least one value at this point */ 2514 assert( i > 0 ); 2515 2516 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 2517 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2518 keys[i].bv_len = index_intlen; 2519 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx ); 2520 } 2521 keys[i].bv_len = 0; 2522 keys[i].bv_val = NULL; 2523 2524 if ( vlen > sizeof(ibuf) ) { 2525 itmp.bv_val = slap_sl_malloc( vlen, ctx ); 2526 } else { 2527 itmp.bv_val = ibuf; 2528 } 2529 itmp.bv_len = sizeof(ibuf); 2530 2531 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 2532 if ( itmp.bv_val != ibuf ) { 2533 itmp.bv_len = values[i].bv_len; 2534 if ( itmp.bv_len <= sizeof(ibuf) ) 2535 itmp.bv_len = sizeof(ibuf); 2536 else if ( itmp.bv_len > maxstrlen ) 2537 itmp.bv_len = maxstrlen; 2538 } 2539 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx ); 2540 if ( rc ) 2541 goto func_leave; 2542 } 2543 *keysp = keys; 2544 func_leave: 2545 if ( itmp.bv_val != ibuf ) { 2546 slap_sl_free( itmp.bv_val, ctx ); 2547 } 2548 return rc; 2549 } 2550 2551 /* Index generation function */ 2552 static int 2553 integerFilter( 2554 slap_mask_t use, 2555 slap_mask_t flags, 2556 Syntax *syntax, 2557 MatchingRule *mr, 2558 struct berval *prefix, 2559 void * assertedValue, 2560 BerVarray *keysp, 2561 void *ctx ) 2562 { 2563 char ibuf[64]; 2564 struct berval iv; 2565 BerVarray keys; 2566 struct berval *value; 2567 int rc; 2568 2569 value = (struct berval *) assertedValue; 2570 2571 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 2572 2573 keys[0].bv_len = index_intlen; 2574 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx ); 2575 keys[1].bv_len = 0; 2576 keys[1].bv_val = NULL; 2577 2578 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1 2579 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2580 if ( iv.bv_len > (int) sizeof(ibuf) ) { 2581 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx ); 2582 } else { 2583 iv.bv_val = ibuf; 2584 iv.bv_len = sizeof(ibuf); 2585 } 2586 2587 rc = integerVal2Key( value, keys, &iv, ctx ); 2588 if ( rc == 0 ) 2589 *keysp = keys; 2590 2591 if ( iv.bv_val != ibuf ) { 2592 slap_sl_free( iv.bv_val, ctx ); 2593 } 2594 return rc; 2595 } 2596 2597 static int 2598 countryStringValidate( 2599 Syntax *syntax, 2600 struct berval *val ) 2601 { 2602 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX; 2603 2604 if( !SLAP_PRINTABLE(val->bv_val[0]) ) { 2605 return LDAP_INVALID_SYNTAX; 2606 } 2607 if( !SLAP_PRINTABLE(val->bv_val[1]) ) { 2608 return LDAP_INVALID_SYNTAX; 2609 } 2610 2611 return LDAP_SUCCESS; 2612 } 2613 2614 static int 2615 printableStringValidate( 2616 Syntax *syntax, 2617 struct berval *val ) 2618 { 2619 ber_len_t i; 2620 2621 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2622 2623 for(i=0; i < val->bv_len; i++) { 2624 if( !SLAP_PRINTABLE(val->bv_val[i]) ) { 2625 return LDAP_INVALID_SYNTAX; 2626 } 2627 } 2628 2629 return LDAP_SUCCESS; 2630 } 2631 2632 static int 2633 printablesStringValidate( 2634 Syntax *syntax, 2635 struct berval *val ) 2636 { 2637 ber_len_t i, len; 2638 2639 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2640 2641 for(i=0,len=0; i < val->bv_len; i++) { 2642 int c = val->bv_val[i]; 2643 2644 if( c == '$' ) { 2645 if( len == 0 ) { 2646 return LDAP_INVALID_SYNTAX; 2647 } 2648 len = 0; 2649 2650 } else if ( SLAP_PRINTABLE(c) ) { 2651 len++; 2652 } else { 2653 return LDAP_INVALID_SYNTAX; 2654 } 2655 } 2656 2657 if( len == 0 ) { 2658 return LDAP_INVALID_SYNTAX; 2659 } 2660 2661 return LDAP_SUCCESS; 2662 } 2663 2664 static int 2665 IA5StringValidate( 2666 Syntax *syntax, 2667 struct berval *val ) 2668 { 2669 ber_len_t i; 2670 2671 for(i=0; i < val->bv_len; i++) { 2672 if( !LDAP_ASCII(val->bv_val[i]) ) { 2673 return LDAP_INVALID_SYNTAX; 2674 } 2675 } 2676 2677 return LDAP_SUCCESS; 2678 } 2679 2680 static int 2681 IA5StringNormalize( 2682 slap_mask_t use, 2683 Syntax *syntax, 2684 MatchingRule *mr, 2685 struct berval *val, 2686 struct berval *normalized, 2687 void *ctx ) 2688 { 2689 char *p, *q; 2690 int casefold = !SLAP_MR_ASSOCIATED( mr, 2691 slap_schema.si_mr_caseExactIA5Match ); 2692 2693 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 2694 2695 p = val->bv_val; 2696 2697 /* Ignore initial whitespace */ 2698 while ( ASCII_SPACE( *p ) ) p++; 2699 2700 normalized->bv_len = val->bv_len - ( p - val->bv_val ); 2701 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2702 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len ); 2703 normalized->bv_val[normalized->bv_len] = '\0'; 2704 2705 p = q = normalized->bv_val; 2706 2707 while ( *p ) { 2708 if ( ASCII_SPACE( *p ) ) { 2709 *q++ = *p++; 2710 2711 /* Ignore the extra whitespace */ 2712 while ( ASCII_SPACE( *p ) ) { 2713 p++; 2714 } 2715 2716 } else if ( casefold ) { 2717 /* Most IA5 rules require casefolding */ 2718 *q++ = TOLOWER(*p); p++; 2719 2720 } else { 2721 *q++ = *p++; 2722 } 2723 } 2724 2725 assert( normalized->bv_val <= p ); 2726 assert( q <= p ); 2727 2728 /* 2729 * If the string ended in space, backup the pointer one 2730 * position. One is enough because the above loop collapsed 2731 * all whitespace to a single space. 2732 */ 2733 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q; 2734 2735 /* null terminate */ 2736 *q = '\0'; 2737 2738 normalized->bv_len = q - normalized->bv_val; 2739 2740 return LDAP_SUCCESS; 2741 } 2742 2743 static int 2744 UUIDValidate( 2745 Syntax *syntax, 2746 struct berval *in ) 2747 { 2748 int i; 2749 if( in->bv_len != 36 ) { 2750 return LDAP_INVALID_SYNTAX; 2751 } 2752 2753 for( i=0; i<36; i++ ) { 2754 switch(i) { 2755 case 8: 2756 case 13: 2757 case 18: 2758 case 23: 2759 if( in->bv_val[i] != '-' ) { 2760 return LDAP_INVALID_SYNTAX; 2761 } 2762 break; 2763 default: 2764 if( !ASCII_HEX( in->bv_val[i]) ) { 2765 return LDAP_INVALID_SYNTAX; 2766 } 2767 } 2768 } 2769 2770 return LDAP_SUCCESS; 2771 } 2772 2773 static int 2774 UUIDPretty( 2775 Syntax *syntax, 2776 struct berval *in, 2777 struct berval *out, 2778 void *ctx ) 2779 { 2780 int i; 2781 int rc=LDAP_INVALID_SYNTAX; 2782 2783 assert( in != NULL ); 2784 assert( out != NULL ); 2785 2786 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX; 2787 2788 out->bv_len = 36; 2789 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 2790 2791 for( i=0; i<36; i++ ) { 2792 switch(i) { 2793 case 8: 2794 case 13: 2795 case 18: 2796 case 23: 2797 if( in->bv_val[i] != '-' ) { 2798 goto handle_error; 2799 } 2800 out->bv_val[i] = '-'; 2801 break; 2802 2803 default: 2804 if( !ASCII_HEX( in->bv_val[i]) ) { 2805 goto handle_error; 2806 } 2807 out->bv_val[i] = TOLOWER( in->bv_val[i] ); 2808 } 2809 } 2810 2811 rc = LDAP_SUCCESS; 2812 out->bv_val[ out->bv_len ] = '\0'; 2813 2814 if( 0 ) { 2815 handle_error: 2816 slap_sl_free( out->bv_val, ctx ); 2817 out->bv_val = NULL; 2818 } 2819 2820 return rc; 2821 } 2822 2823 int 2824 UUIDNormalize( 2825 slap_mask_t usage, 2826 Syntax *syntax, 2827 MatchingRule *mr, 2828 struct berval *val, 2829 struct berval *normalized, 2830 void *ctx ) 2831 { 2832 unsigned char octet = '\0'; 2833 int i; 2834 int j; 2835 2836 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) { 2837 /* NOTE: must be a normalized UUID */ 2838 assert( val->bv_len == 16 ); 2839 2840 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx ); 2841 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val, 2842 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE ); 2843 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) ); 2844 2845 return LDAP_SUCCESS; 2846 } 2847 2848 normalized->bv_len = 16; 2849 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2850 2851 for( i=0, j=0; i<36; i++ ) { 2852 unsigned char nibble; 2853 if( val->bv_val[i] == '-' ) { 2854 continue; 2855 2856 } else if( ASCII_DIGIT( val->bv_val[i] ) ) { 2857 nibble = val->bv_val[i] - '0'; 2858 2859 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) { 2860 nibble = val->bv_val[i] - ('a'-10); 2861 2862 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) { 2863 nibble = val->bv_val[i] - ('A'-10); 2864 2865 } else { 2866 slap_sl_free( normalized->bv_val, ctx ); 2867 BER_BVZERO( normalized ); 2868 return LDAP_INVALID_SYNTAX; 2869 } 2870 2871 if( j & 1 ) { 2872 octet |= nibble; 2873 normalized->bv_val[j>>1] = octet; 2874 } else { 2875 octet = nibble << 4; 2876 } 2877 j++; 2878 } 2879 2880 normalized->bv_val[normalized->bv_len] = 0; 2881 return LDAP_SUCCESS; 2882 } 2883 2884 2885 2886 int 2887 numericStringValidate( 2888 Syntax *syntax, 2889 struct berval *in ) 2890 { 2891 ber_len_t i; 2892 2893 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX; 2894 2895 for(i=0; i < in->bv_len; i++) { 2896 if( !SLAP_NUMERIC(in->bv_val[i]) ) { 2897 return LDAP_INVALID_SYNTAX; 2898 } 2899 } 2900 2901 return LDAP_SUCCESS; 2902 } 2903 2904 static int 2905 numericStringNormalize( 2906 slap_mask_t usage, 2907 Syntax *syntax, 2908 MatchingRule *mr, 2909 struct berval *val, 2910 struct berval *normalized, 2911 void *ctx ) 2912 { 2913 /* removal all spaces */ 2914 char *p, *q; 2915 2916 assert( !BER_BVISEMPTY( val ) ); 2917 2918 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 2919 2920 p = val->bv_val; 2921 q = normalized->bv_val; 2922 2923 while ( *p ) { 2924 if ( ASCII_SPACE( *p ) ) { 2925 /* Ignore whitespace */ 2926 p++; 2927 } else { 2928 *q++ = *p++; 2929 } 2930 } 2931 2932 /* we should have copied no more than is in val */ 2933 assert( (q - normalized->bv_val) <= (p - val->bv_val) ); 2934 2935 /* null terminate */ 2936 *q = '\0'; 2937 2938 normalized->bv_len = q - normalized->bv_val; 2939 2940 if( BER_BVISEMPTY( normalized ) ) { 2941 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx ); 2942 normalized->bv_val[0] = ' '; 2943 normalized->bv_val[1] = '\0'; 2944 normalized->bv_len = 1; 2945 } 2946 2947 return LDAP_SUCCESS; 2948 } 2949 2950 /* 2951 * Integer conversion macros that will use the largest available 2952 * type. 2953 */ 2954 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) 2955 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) 2956 # define SLAP_LONG long long 2957 #else 2958 # define SLAP_STRTOL(n,e,b) strtol(n,e,b) 2959 # define SLAP_LONG long 2960 #endif /* HAVE_STRTOLL ... */ 2961 2962 static int 2963 integerBitAndMatch( 2964 int *matchp, 2965 slap_mask_t flags, 2966 Syntax *syntax, 2967 MatchingRule *mr, 2968 struct berval *value, 2969 void *assertedValue ) 2970 { 2971 SLAP_LONG lValue, lAssertedValue; 2972 2973 errno = 0; 2974 /* safe to assume integers are NUL terminated? */ 2975 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 2976 if( errno == ERANGE ) 2977 { 2978 return LDAP_CONSTRAINT_VIOLATION; 2979 } 2980 2981 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, 2982 NULL, 10); 2983 if( errno == ERANGE ) 2984 { 2985 return LDAP_CONSTRAINT_VIOLATION; 2986 } 2987 2988 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1; 2989 return LDAP_SUCCESS; 2990 } 2991 2992 static int 2993 integerBitOrMatch( 2994 int *matchp, 2995 slap_mask_t flags, 2996 Syntax *syntax, 2997 MatchingRule *mr, 2998 struct berval *value, 2999 void *assertedValue ) 3000 { 3001 SLAP_LONG lValue, lAssertedValue; 3002 3003 errno = 0; 3004 /* safe to assume integers are NUL terminated? */ 3005 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 3006 if( errno == ERANGE ) 3007 { 3008 return LDAP_CONSTRAINT_VIOLATION; 3009 } 3010 3011 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, 3012 NULL, 10); 3013 if( errno == ERANGE ) 3014 { 3015 return LDAP_CONSTRAINT_VIOLATION; 3016 } 3017 3018 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1; 3019 return LDAP_SUCCESS; 3020 } 3021 3022 static int 3023 checkNum( struct berval *in, struct berval *out ) 3024 { 3025 /* parse serialNumber */ 3026 ber_len_t neg = 0, extra = 0; 3027 char first = '\0'; 3028 3029 out->bv_val = in->bv_val; 3030 out->bv_len = 0; 3031 3032 if ( out->bv_val[0] == '-' ) { 3033 neg++; 3034 out->bv_len++; 3035 } 3036 3037 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) { 3038 first = out->bv_val[2]; 3039 extra = 2; 3040 3041 out->bv_len += STRLENOF("0x"); 3042 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3043 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break; 3044 } 3045 3046 } else if ( out->bv_val[0] == '\'' ) { 3047 first = out->bv_val[1]; 3048 extra = 3; 3049 3050 out->bv_len += STRLENOF("'"); 3051 3052 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3053 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break; 3054 } 3055 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) { 3056 return -1; 3057 } 3058 out->bv_len += STRLENOF("'H"); 3059 3060 } else { 3061 first = out->bv_val[0]; 3062 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3063 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break; 3064 } 3065 } 3066 3067 if ( !( out->bv_len > neg ) ) { 3068 return -1; 3069 } 3070 3071 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) { 3072 return -1; 3073 } 3074 3075 return 0; 3076 } 3077 3078 static int 3079 serialNumberAndIssuerCheck( 3080 struct berval *in, 3081 struct berval *sn, 3082 struct berval *is, 3083 void *ctx ) 3084 { 3085 ber_len_t n; 3086 3087 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 3088 3089 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 3090 /* Parse old format */ 3091 is->bv_val = ber_bvchr( in, '$' ); 3092 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX; 3093 3094 sn->bv_val = in->bv_val; 3095 sn->bv_len = is->bv_val - in->bv_val; 3096 3097 is->bv_val++; 3098 is->bv_len = in->bv_len - (sn->bv_len + 1); 3099 3100 /* eat leading zeros */ 3101 for( n=0; n < (sn->bv_len-1); n++ ) { 3102 if( sn->bv_val[n] != '0' ) break; 3103 } 3104 sn->bv_val += n; 3105 sn->bv_len -= n; 3106 3107 for( n=0; n < sn->bv_len; n++ ) { 3108 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX; 3109 } 3110 3111 } else { 3112 /* Parse GSER format */ 3113 enum { 3114 HAVE_NONE = 0x0, 3115 HAVE_ISSUER = 0x1, 3116 HAVE_SN = 0x2, 3117 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN ) 3118 } have = HAVE_NONE; 3119 3120 int numdquotes = 0; 3121 struct berval x = *in; 3122 struct berval ni; 3123 x.bv_val++; 3124 x.bv_len -= 2; 3125 3126 do { 3127 /* eat leading spaces */ 3128 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3129 /* empty */; 3130 } 3131 3132 /* should be at issuer or serialNumber NamedValue */ 3133 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 3134 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX; 3135 3136 /* parse issuer */ 3137 x.bv_val += STRLENOF("issuer"); 3138 x.bv_len -= STRLENOF("issuer"); 3139 3140 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3141 x.bv_val++; 3142 x.bv_len--; 3143 3144 /* eat leading spaces */ 3145 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3146 /* empty */; 3147 } 3148 3149 /* For backward compatibility, this part is optional */ 3150 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) { 3151 x.bv_val += STRLENOF("rdnSequence:"); 3152 x.bv_len -= STRLENOF("rdnSequence:"); 3153 } 3154 3155 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3156 x.bv_val++; 3157 x.bv_len--; 3158 3159 is->bv_val = x.bv_val; 3160 is->bv_len = 0; 3161 3162 for ( ; is->bv_len < x.bv_len; ) { 3163 if ( is->bv_val[is->bv_len] != '"' ) { 3164 is->bv_len++; 3165 continue; 3166 } 3167 if ( is->bv_val[is->bv_len+1] == '"' ) { 3168 /* double dquote */ 3169 is->bv_len += 2; 3170 continue; 3171 } 3172 break; 3173 } 3174 x.bv_val += is->bv_len + 1; 3175 x.bv_len -= is->bv_len + 1; 3176 3177 have |= HAVE_ISSUER; 3178 3179 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) 3180 { 3181 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX; 3182 3183 /* parse serialNumber */ 3184 x.bv_val += STRLENOF("serialNumber"); 3185 x.bv_len -= STRLENOF("serialNumber"); 3186 3187 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3188 x.bv_val++; 3189 x.bv_len--; 3190 3191 /* eat leading spaces */ 3192 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3193 /* empty */; 3194 } 3195 3196 if ( checkNum( &x, sn ) ) { 3197 return LDAP_INVALID_SYNTAX; 3198 } 3199 3200 x.bv_val += sn->bv_len; 3201 x.bv_len -= sn->bv_len; 3202 3203 have |= HAVE_SN; 3204 3205 } else { 3206 return LDAP_INVALID_SYNTAX; 3207 } 3208 3209 /* eat leading spaces */ 3210 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3211 /* empty */; 3212 } 3213 3214 if ( have == HAVE_ALL ) { 3215 break; 3216 } 3217 3218 if ( x.bv_val[0] != ',' ) { 3219 return LDAP_INVALID_SYNTAX; 3220 } 3221 3222 x.bv_val++; 3223 x.bv_len--; 3224 } while ( 1 ); 3225 3226 /* should have no characters left... */ 3227 if ( x.bv_len ) return LDAP_INVALID_SYNTAX; 3228 3229 if ( numdquotes == 0 ) { 3230 ber_dupbv_x( &ni, is, ctx ); 3231 3232 } else { 3233 ber_len_t src, dst; 3234 3235 ni.bv_len = is->bv_len - numdquotes; 3236 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 3237 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 3238 if ( is->bv_val[src] == '"' ) { 3239 src++; 3240 } 3241 ni.bv_val[dst] = is->bv_val[src]; 3242 } 3243 ni.bv_val[dst] = '\0'; 3244 } 3245 3246 *is = ni; 3247 } 3248 3249 return 0; 3250 } 3251 3252 static int 3253 serialNumberAndIssuerValidate( 3254 Syntax *syntax, 3255 struct berval *in ) 3256 { 3257 int rc; 3258 struct berval sn, i; 3259 3260 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n", 3261 in->bv_val, 0, 0 ); 3262 3263 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL ); 3264 if ( rc ) { 3265 goto done; 3266 } 3267 3268 /* validate DN -- doesn't handle double dquote */ 3269 rc = dnValidate( NULL, &i ); 3270 if ( rc ) { 3271 rc = LDAP_INVALID_SYNTAX; 3272 } 3273 3274 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3275 slap_sl_free( i.bv_val, NULL ); 3276 } 3277 3278 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n", 3279 in->bv_val, rc, 0 ); 3280 3281 done:; 3282 return rc; 3283 } 3284 3285 static int 3286 serialNumberAndIssuerPretty( 3287 Syntax *syntax, 3288 struct berval *in, 3289 struct berval *out, 3290 void *ctx ) 3291 { 3292 int rc; 3293 struct berval sn, i, ni = BER_BVNULL; 3294 char *p; 3295 3296 assert( in != NULL ); 3297 assert( out != NULL ); 3298 3299 BER_BVZERO( out ); 3300 3301 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", 3302 in->bv_val, 0, 0 ); 3303 3304 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3305 if ( rc ) { 3306 goto done; 3307 } 3308 3309 rc = dnPretty( syntax, &i, &ni, ctx ); 3310 3311 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3312 slap_sl_free( i.bv_val, ctx ); 3313 } 3314 3315 if ( rc ) { 3316 rc = LDAP_INVALID_SYNTAX; 3317 goto done; 3318 } 3319 3320 /* make room from sn + "$" */ 3321 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }") 3322 + sn.bv_len + ni.bv_len; 3323 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3324 3325 if ( out->bv_val == NULL ) { 3326 out->bv_len = 0; 3327 rc = LDAP_OTHER; 3328 goto done; 3329 } 3330 3331 p = out->bv_val; 3332 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3333 p = lutil_strbvcopy( p, &sn ); 3334 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3335 p = lutil_strbvcopy( p, &ni ); 3336 p = lutil_strcopy( p, /*{*/ "\" }" ); 3337 3338 assert( p == &out->bv_val[out->bv_len] ); 3339 3340 done:; 3341 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n", 3342 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 3343 3344 slap_sl_free( ni.bv_val, ctx ); 3345 3346 return LDAP_SUCCESS; 3347 } 3348 3349 static int 3350 slap_bin2hex( 3351 struct berval *in, 3352 struct berval *out, 3353 void *ctx ) 3354 3355 { 3356 /* Use hex format. '123456789abcdef'H */ 3357 unsigned char *ptr, zero = '\0'; 3358 char *sptr; 3359 int first; 3360 ber_len_t i, len, nlen; 3361 3362 assert( in != NULL ); 3363 assert( !BER_BVISNULL( in ) ); 3364 assert( out != NULL ); 3365 assert( !BER_BVISNULL( out ) ); 3366 3367 ptr = (unsigned char *)in->bv_val; 3368 len = in->bv_len; 3369 3370 /* Check for minimal encodings */ 3371 if ( len > 1 ) { 3372 if ( ptr[0] & 0x80 ) { 3373 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) { 3374 return -1; 3375 } 3376 3377 } else if ( ptr[0] == 0 ) { 3378 if ( !( ptr[1] & 0x80 ) ) { 3379 return -1; 3380 } 3381 len--; 3382 ptr++; 3383 } 3384 3385 } else if ( len == 0 ) { 3386 /* FIXME: this should not be possible, 3387 * since a value of zero would have length 1 */ 3388 len = 1; 3389 ptr = &zero; 3390 } 3391 3392 first = !( ptr[0] & 0xf0U ); 3393 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */ 3394 if ( nlen >= out->bv_len ) { 3395 out->bv_val = slap_sl_malloc( nlen + 1, ctx ); 3396 } 3397 sptr = out->bv_val; 3398 *sptr++ = '\''; 3399 i = 0; 3400 if ( first ) { 3401 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) ); 3402 sptr++; 3403 i = 1; 3404 } 3405 for ( ; i < len; i++ ) { 3406 sprintf( sptr, "%02X", ptr[i] ); 3407 sptr += 2; 3408 } 3409 *sptr++ = '\''; 3410 *sptr++ = 'H'; 3411 *sptr = '\0'; 3412 3413 assert( sptr == &out->bv_val[nlen] ); 3414 3415 out->bv_len = nlen; 3416 3417 return 0; 3418 } 3419 3420 #define SLAP_SN_BUFLEN (64) 3421 3422 /* 3423 * This routine is called by certificateExactNormalize when 3424 * certificateExactNormalize receives a search string instead of 3425 * a certificate. This routine checks if the search value is valid 3426 * and then returns the normalized value 3427 */ 3428 static int 3429 serialNumberAndIssuerNormalize( 3430 slap_mask_t usage, 3431 Syntax *syntax, 3432 MatchingRule *mr, 3433 struct berval *in, 3434 struct berval *out, 3435 void *ctx ) 3436 { 3437 struct berval sn, sn2, sn3, i, ni; 3438 char sbuf2[SLAP_SN_BUFLEN]; 3439 char sbuf3[SLAP_SN_BUFLEN]; 3440 char *p; 3441 int rc; 3442 3443 assert( in != NULL ); 3444 assert( out != NULL ); 3445 3446 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", 3447 in->bv_val, 0, 0 ); 3448 3449 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3450 if ( rc ) { 3451 return rc; 3452 } 3453 3454 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 3455 3456 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3457 slap_sl_free( i.bv_val, ctx ); 3458 } 3459 3460 if ( rc ) { 3461 return LDAP_INVALID_SYNTAX; 3462 } 3463 3464 /* Convert sn to canonical hex */ 3465 sn2.bv_val = sbuf2; 3466 if ( sn.bv_len > sizeof( sbuf2 ) ) { 3467 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx ); 3468 } 3469 sn2.bv_len = sn.bv_len; 3470 if ( lutil_str2bin( &sn, &sn2, ctx )) { 3471 rc = LDAP_INVALID_SYNTAX; 3472 goto func_leave; 3473 } 3474 3475 sn3.bv_val = sbuf3; 3476 sn3.bv_len = sizeof(sbuf3); 3477 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) { 3478 rc = LDAP_INVALID_SYNTAX; 3479 goto func_leave; 3480 } 3481 3482 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3483 + sn3.bv_len + ni.bv_len; 3484 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3485 3486 if ( out->bv_val == NULL ) { 3487 out->bv_len = 0; 3488 rc = LDAP_OTHER; 3489 goto func_leave; 3490 } 3491 3492 p = out->bv_val; 3493 3494 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3495 p = lutil_strbvcopy( p, &sn3 ); 3496 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3497 p = lutil_strbvcopy( p, &ni ); 3498 p = lutil_strcopy( p, /*{*/ "\" }" ); 3499 3500 assert( p == &out->bv_val[out->bv_len] ); 3501 3502 func_leave: 3503 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n", 3504 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 3505 3506 if ( sn2.bv_val != sbuf2 ) { 3507 slap_sl_free( sn2.bv_val, ctx ); 3508 } 3509 3510 if ( sn3.bv_val != sbuf3 ) { 3511 slap_sl_free( sn3.bv_val, ctx ); 3512 } 3513 3514 slap_sl_free( ni.bv_val, ctx ); 3515 3516 return rc; 3517 } 3518 3519 static int 3520 certificateExactNormalize( 3521 slap_mask_t usage, 3522 Syntax *syntax, 3523 MatchingRule *mr, 3524 struct berval *val, 3525 struct berval *normalized, 3526 void *ctx ) 3527 { 3528 BerElementBuffer berbuf; 3529 BerElement *ber = (BerElement *)&berbuf; 3530 ber_tag_t tag; 3531 ber_len_t len; 3532 ber_int_t i; 3533 char serialbuf2[SLAP_SN_BUFLEN]; 3534 struct berval sn, sn2 = BER_BVNULL; 3535 struct berval issuer_dn = BER_BVNULL, bvdn; 3536 char *p; 3537 int rc = LDAP_INVALID_SYNTAX; 3538 3539 assert( val != NULL ); 3540 3541 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n", 3542 val->bv_val, val->bv_len, 0 ); 3543 3544 if ( BER_BVISEMPTY( val ) ) goto done; 3545 3546 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3547 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx ); 3548 } 3549 3550 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3551 3552 ber_init2( ber, val, LBER_USE_DER ); 3553 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 3554 tag = ber_skip_tag( ber, &len ); /* Sequence */ 3555 tag = ber_peek_tag( ber, &len ); /* Optional version? */ 3556 if ( tag == SLAP_X509_OPT_C_VERSION ) { 3557 tag = ber_skip_tag( ber, &len ); 3558 tag = ber_get_int( ber, &i ); /* version */ 3559 } 3560 3561 /* NOTE: move the test here from certificateValidate, 3562 * so that we can validate certs with serial longer 3563 * than sizeof(ber_int_t) */ 3564 tag = ber_skip_tag( ber, &len ); /* serial */ 3565 sn.bv_len = len; 3566 sn.bv_val = (char *)ber->ber_ptr; 3567 sn2.bv_val = serialbuf2; 3568 sn2.bv_len = sizeof(serialbuf2); 3569 if ( slap_bin2hex( &sn, &sn2, ctx ) ) { 3570 rc = LDAP_INVALID_SYNTAX; 3571 goto done; 3572 } 3573 ber_skip_data( ber, len ); 3574 3575 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */ 3576 ber_skip_data( ber, len ); 3577 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 3578 len = ber_ptrlen( ber ); 3579 bvdn.bv_val = val->bv_val + len; 3580 bvdn.bv_len = val->bv_len - len; 3581 3582 rc = dnX509normalize( &bvdn, &issuer_dn ); 3583 if ( rc != LDAP_SUCCESS ) goto done; 3584 3585 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3586 + sn2.bv_len + issuer_dn.bv_len; 3587 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 3588 3589 p = normalized->bv_val; 3590 3591 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3592 p = lutil_strbvcopy( p, &sn2 ); 3593 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3594 p = lutil_strbvcopy( p, &issuer_dn ); 3595 p = lutil_strcopy( p, /*{*/ "\" }" ); 3596 3597 rc = LDAP_SUCCESS; 3598 3599 done: 3600 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n", 3601 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" ); 3602 3603 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 3604 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx ); 3605 3606 return rc; 3607 } 3608 3609 /* X.509 PKI certificateList stuff */ 3610 static int 3611 checkTime( struct berval *in, struct berval *out ) 3612 { 3613 int rc; 3614 ber_len_t i; 3615 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 3616 struct berval bv; 3617 3618 assert( in != NULL ); 3619 assert( !BER_BVISNULL( in ) ); 3620 assert( !BER_BVISEMPTY( in ) ); 3621 3622 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) { 3623 return -1; 3624 } 3625 3626 if ( out != NULL ) { 3627 assert( !BER_BVISNULL( out ) ); 3628 assert( out->bv_len >= sizeof( buf ) ); 3629 bv.bv_val = out->bv_val; 3630 3631 } else { 3632 bv.bv_val = buf; 3633 } 3634 3635 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) { 3636 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break; 3637 } 3638 3639 if ( in->bv_val[i] != 'Z' ) { 3640 return -1; 3641 } 3642 i++; 3643 3644 if ( i != in->bv_len ) { 3645 return -1; 3646 } 3647 3648 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 3649 lutil_strncopy( bv.bv_val, in->bv_val, i ); 3650 bv.bv_len = i; 3651 3652 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) { 3653 char *p = bv.bv_val; 3654 if ( in->bv_val[0] < '7' ) { 3655 p = lutil_strcopy( p, "20" ); 3656 3657 } else { 3658 p = lutil_strcopy( p, "19" ); 3659 } 3660 lutil_strncopy( p, in->bv_val, i ); 3661 bv.bv_len = 2 + i; 3662 3663 } else { 3664 return -1; 3665 } 3666 3667 rc = generalizedTimeValidate( NULL, &bv ); 3668 if ( rc == LDAP_SUCCESS && out != NULL ) { 3669 if ( out->bv_len > bv.bv_len ) { 3670 out->bv_val[ bv.bv_len ] = '\0'; 3671 } 3672 out->bv_len = bv.bv_len; 3673 } 3674 3675 return rc != LDAP_SUCCESS; 3676 } 3677 3678 static int 3679 issuerAndThisUpdateCheck( 3680 struct berval *in, 3681 struct berval *is, 3682 struct berval *tu, 3683 void *ctx ) 3684 { 3685 int numdquotes = 0; 3686 struct berval x = *in; 3687 struct berval ni = BER_BVNULL; 3688 /* Parse GSER format */ 3689 enum { 3690 HAVE_NONE = 0x0, 3691 HAVE_ISSUER = 0x1, 3692 HAVE_THISUPDATE = 0x2, 3693 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE ) 3694 } have = HAVE_NONE; 3695 3696 3697 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX; 3698 3699 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 3700 return LDAP_INVALID_SYNTAX; 3701 } 3702 3703 x.bv_val++; 3704 x.bv_len -= STRLENOF("{}"); 3705 3706 do { 3707 /* eat leading spaces */ 3708 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3709 /* empty */; 3710 } 3711 3712 /* should be at issuer or thisUpdate */ 3713 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 3714 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX; 3715 3716 /* parse issuer */ 3717 x.bv_val += STRLENOF("issuer"); 3718 x.bv_len -= STRLENOF("issuer"); 3719 3720 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3721 x.bv_val++; 3722 x.bv_len--; 3723 3724 /* eat leading spaces */ 3725 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3726 /* empty */; 3727 } 3728 3729 /* For backward compatibility, this part is optional */ 3730 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) { 3731 return LDAP_INVALID_SYNTAX; 3732 } 3733 x.bv_val += STRLENOF("rdnSequence:"); 3734 x.bv_len -= STRLENOF("rdnSequence:"); 3735 3736 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3737 x.bv_val++; 3738 x.bv_len--; 3739 3740 is->bv_val = x.bv_val; 3741 is->bv_len = 0; 3742 3743 for ( ; is->bv_len < x.bv_len; ) { 3744 if ( is->bv_val[is->bv_len] != '"' ) { 3745 is->bv_len++; 3746 continue; 3747 } 3748 if ( is->bv_val[is->bv_len+1] == '"' ) { 3749 /* double dquote */ 3750 is->bv_len += 2; 3751 continue; 3752 } 3753 break; 3754 } 3755 x.bv_val += is->bv_len + 1; 3756 x.bv_len -= is->bv_len + 1; 3757 3758 have |= HAVE_ISSUER; 3759 3760 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 ) 3761 { 3762 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX; 3763 3764 /* parse thisUpdate */ 3765 x.bv_val += STRLENOF("thisUpdate"); 3766 x.bv_len -= STRLENOF("thisUpdate"); 3767 3768 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3769 x.bv_val++; 3770 x.bv_len--; 3771 3772 /* eat leading spaces */ 3773 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3774 /* empty */; 3775 } 3776 3777 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3778 x.bv_val++; 3779 x.bv_len--; 3780 3781 tu->bv_val = x.bv_val; 3782 tu->bv_len = 0; 3783 3784 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) { 3785 if ( tu->bv_val[tu->bv_len] == '"' ) { 3786 break; 3787 } 3788 } 3789 x.bv_val += tu->bv_len + 1; 3790 x.bv_len -= tu->bv_len + 1; 3791 3792 have |= HAVE_THISUPDATE; 3793 3794 } else { 3795 return LDAP_INVALID_SYNTAX; 3796 } 3797 3798 /* eat leading spaces */ 3799 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3800 /* empty */; 3801 } 3802 3803 if ( have == HAVE_ALL ) { 3804 break; 3805 } 3806 3807 if ( x.bv_val[0] != ',' ) { 3808 return LDAP_INVALID_SYNTAX; 3809 } 3810 3811 x.bv_val++; 3812 x.bv_len--; 3813 } while ( 1 ); 3814 3815 /* should have no characters left... */ 3816 if ( x.bv_len ) return LDAP_INVALID_SYNTAX; 3817 3818 if ( numdquotes == 0 ) { 3819 ber_dupbv_x( &ni, is, ctx ); 3820 3821 } else { 3822 ber_len_t src, dst; 3823 3824 ni.bv_len = is->bv_len - numdquotes; 3825 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 3826 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 3827 if ( is->bv_val[src] == '"' ) { 3828 src++; 3829 } 3830 ni.bv_val[dst] = is->bv_val[src]; 3831 } 3832 ni.bv_val[dst] = '\0'; 3833 } 3834 3835 *is = ni; 3836 3837 return 0; 3838 } 3839 3840 static int 3841 issuerAndThisUpdateValidate( 3842 Syntax *syntax, 3843 struct berval *in ) 3844 { 3845 int rc; 3846 struct berval i, tu; 3847 3848 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n", 3849 in->bv_val, 0, 0 ); 3850 3851 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL ); 3852 if ( rc ) { 3853 goto done; 3854 } 3855 3856 /* validate DN -- doesn't handle double dquote */ 3857 rc = dnValidate( NULL, &i ); 3858 if ( rc ) { 3859 rc = LDAP_INVALID_SYNTAX; 3860 3861 } else if ( checkTime( &tu, NULL ) ) { 3862 rc = LDAP_INVALID_SYNTAX; 3863 } 3864 3865 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3866 slap_sl_free( i.bv_val, NULL ); 3867 } 3868 3869 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n", 3870 in->bv_val, rc, 0 ); 3871 3872 done:; 3873 return rc; 3874 } 3875 3876 static int 3877 issuerAndThisUpdatePretty( 3878 Syntax *syntax, 3879 struct berval *in, 3880 struct berval *out, 3881 void *ctx ) 3882 { 3883 int rc; 3884 struct berval i, tu, ni = BER_BVNULL; 3885 char *p; 3886 3887 assert( in != NULL ); 3888 assert( out != NULL ); 3889 3890 BER_BVZERO( out ); 3891 3892 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n", 3893 in->bv_val, 0, 0 ); 3894 3895 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx ); 3896 if ( rc ) { 3897 goto done; 3898 } 3899 3900 rc = dnPretty( syntax, &i, &ni, ctx ); 3901 3902 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3903 slap_sl_free( i.bv_val, ctx ); 3904 } 3905 3906 if ( rc || checkTime( &tu, NULL ) ) { 3907 rc = LDAP_INVALID_SYNTAX; 3908 goto done; 3909 } 3910 3911 /* make room */ 3912 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }") 3913 + ni.bv_len + tu.bv_len; 3914 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3915 3916 if ( out->bv_val == NULL ) { 3917 out->bv_len = 0; 3918 rc = LDAP_OTHER; 3919 goto done; 3920 } 3921 3922 p = out->bv_val; 3923 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ ); 3924 p = lutil_strbvcopy( p, &ni ); 3925 p = lutil_strcopy( p, "\", thisUpdate \"" ); 3926 p = lutil_strbvcopy( p, &tu ); 3927 p = lutil_strcopy( p, /*{*/ "\" }" ); 3928 3929 assert( p == &out->bv_val[out->bv_len] ); 3930 3931 done:; 3932 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n", 3933 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 3934 3935 slap_sl_free( ni.bv_val, ctx ); 3936 3937 return rc; 3938 } 3939 3940 static int 3941 issuerAndThisUpdateNormalize( 3942 slap_mask_t usage, 3943 Syntax *syntax, 3944 MatchingRule *mr, 3945 struct berval *in, 3946 struct berval *out, 3947 void *ctx ) 3948 { 3949 struct berval i, ni, tu, tu2; 3950 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 3951 char *p; 3952 int rc; 3953 3954 assert( in != NULL ); 3955 assert( out != NULL ); 3956 3957 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n", 3958 in->bv_val, 0, 0 ); 3959 3960 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx ); 3961 if ( rc ) { 3962 return rc; 3963 } 3964 3965 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 3966 3967 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3968 slap_sl_free( i.bv_val, ctx ); 3969 } 3970 3971 tu2.bv_val = sbuf; 3972 tu2.bv_len = sizeof( sbuf ); 3973 if ( rc || checkTime( &tu, &tu2 ) ) { 3974 return LDAP_INVALID_SYNTAX; 3975 } 3976 3977 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" ) 3978 + ni.bv_len + tu2.bv_len; 3979 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3980 3981 if ( out->bv_val == NULL ) { 3982 out->bv_len = 0; 3983 rc = LDAP_OTHER; 3984 goto func_leave; 3985 } 3986 3987 p = out->bv_val; 3988 3989 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ ); 3990 p = lutil_strbvcopy( p, &ni ); 3991 p = lutil_strcopy( p, "\", thisUpdate \"" ); 3992 p = lutil_strbvcopy( p, &tu2 ); 3993 p = lutil_strcopy( p, /*{*/ "\" }" ); 3994 3995 assert( p == &out->bv_val[out->bv_len] ); 3996 3997 func_leave: 3998 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n", 3999 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4000 4001 slap_sl_free( ni.bv_val, ctx ); 4002 4003 return rc; 4004 } 4005 4006 static int 4007 certificateListExactNormalize( 4008 slap_mask_t usage, 4009 Syntax *syntax, 4010 MatchingRule *mr, 4011 struct berval *val, 4012 struct berval *normalized, 4013 void *ctx ) 4014 { 4015 BerElementBuffer berbuf; 4016 BerElement *ber = (BerElement *)&berbuf; 4017 ber_tag_t tag; 4018 ber_len_t len; 4019 ber_int_t version; 4020 struct berval issuer_dn = BER_BVNULL, bvdn, 4021 thisUpdate, bvtu; 4022 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 4023 int rc = LDAP_INVALID_SYNTAX; 4024 4025 assert( val != NULL ); 4026 4027 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n", 4028 val->bv_val, val->bv_len, 0 ); 4029 4030 if ( BER_BVISEMPTY( val ) ) goto done; 4031 4032 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 4033 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx ); 4034 } 4035 4036 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 4037 4038 ber_init2( ber, val, LBER_USE_DER ); 4039 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 4040 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4041 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4042 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4043 tag = ber_peek_tag( ber, &len ); 4044 /* Optional version */ 4045 if ( tag == LBER_INTEGER ) { 4046 tag = ber_get_int( ber, &version ); 4047 assert( tag == LBER_INTEGER ); 4048 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 4049 } 4050 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 4051 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4052 ber_skip_data( ber, len ); 4053 4054 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 4055 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4056 len = ber_ptrlen( ber ); 4057 bvdn.bv_val = val->bv_val + len; 4058 bvdn.bv_len = val->bv_len - len; 4059 tag = ber_skip_tag( ber, &len ); 4060 ber_skip_data( ber, len ); 4061 4062 tag = ber_skip_tag( ber, &len ); /* thisUpdate */ 4063 /* Time is a CHOICE { UTCTime, GeneralizedTime } */ 4064 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX; 4065 bvtu.bv_val = (char *)ber->ber_ptr; 4066 bvtu.bv_len = len; 4067 4068 rc = dnX509normalize( &bvdn, &issuer_dn ); 4069 if ( rc != LDAP_SUCCESS ) goto done; 4070 4071 thisUpdate.bv_val = tubuf; 4072 thisUpdate.bv_len = sizeof(tubuf); 4073 if ( checkTime( &bvtu, &thisUpdate ) ) { 4074 rc = LDAP_INVALID_SYNTAX; 4075 goto done; 4076 } 4077 4078 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" ) 4079 + issuer_dn.bv_len + thisUpdate.bv_len; 4080 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 4081 4082 p = normalized->bv_val; 4083 4084 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" ); 4085 p = lutil_strbvcopy( p, &issuer_dn ); 4086 p = lutil_strcopy( p, "\", thisUpdate \"" ); 4087 p = lutil_strbvcopy( p, &thisUpdate ); 4088 p = lutil_strcopy( p, /*{*/ "\" }" ); 4089 4090 rc = LDAP_SUCCESS; 4091 4092 done: 4093 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n", 4094 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" ); 4095 4096 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 4097 4098 return rc; 4099 } 4100 4101 /* X.509 PMI serialNumberAndIssuerSerialCheck 4102 4103 AttributeCertificateExactAssertion ::= SEQUENCE { 4104 serialNumber CertificateSerialNumber, 4105 issuer AttCertIssuer } 4106 4107 CertificateSerialNumber ::= INTEGER 4108 4109 AttCertIssuer ::= [0] SEQUENCE { 4110 issuerName GeneralNames OPTIONAL, 4111 baseCertificateID [0] IssuerSerial OPTIONAL, 4112 objectDigestInfo [1] ObjectDigestInfo OPTIONAL } 4113 -- At least one component shall be present 4114 4115 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 4116 4117 GeneralName ::= CHOICE { 4118 otherName [0] INSTANCE OF OTHER-NAME, 4119 rfc822Name [1] IA5String, 4120 dNSName [2] IA5String, 4121 x400Address [3] ORAddress, 4122 directoryName [4] Name, 4123 ediPartyName [5] EDIPartyName, 4124 uniformResourceIdentifier [6] IA5String, 4125 iPAddress [7] OCTET STRING, 4126 registeredID [8] OBJECT IDENTIFIER } 4127 4128 IssuerSerial ::= SEQUENCE { 4129 issuer GeneralNames, 4130 serial CertificateSerialNumber, 4131 issuerUID UniqueIdentifier OPTIONAL } 4132 4133 ObjectDigestInfo ::= SEQUENCE { 4134 digestedObjectType ENUMERATED { 4135 publicKey (0), 4136 publicKeyCert (1), 4137 otherObjectTypes (2) }, 4138 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL, 4139 digestAlgorithm AlgorithmIdentifier, 4140 objectDigest BIT STRING } 4141 4142 * The way I interpret it, an assertion should look like 4143 4144 { serialNumber 'dd'H, 4145 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional 4146 baseCertificateID { serial '1d'H, 4147 issuer { directoryName:rdnSequence:"cn=zzz" }, 4148 issuerUID <value> -- optional 4149 }, -- optional 4150 objectDigestInfo { ... } -- optional 4151 } 4152 } 4153 4154 * with issuerName, baseCertificateID and objectDigestInfo optional, 4155 * at least one present; the way it's currently implemented, it is 4156 4157 { serialNumber 'dd'H, 4158 issuer { baseCertificateID { serial '1d'H, 4159 issuer { directoryName:rdnSequence:"cn=zzz" } 4160 } 4161 } 4162 } 4163 4164 * with all the above parts mandatory. 4165 */ 4166 static int 4167 serialNumberAndIssuerSerialCheck( 4168 struct berval *in, 4169 struct berval *sn, 4170 struct berval *is, 4171 struct berval *i_sn, /* contain serial of baseCertificateID */ 4172 void *ctx ) 4173 { 4174 /* Parse GSER format */ 4175 enum { 4176 HAVE_NONE = 0x0, 4177 HAVE_SN = 0x1, 4178 HAVE_ISSUER = 0x2, 4179 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER ) 4180 } have = HAVE_NONE, have2 = HAVE_NONE; 4181 int numdquotes = 0; 4182 struct berval x = *in; 4183 struct berval ni; 4184 4185 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4186 4187 /* no old format */ 4188 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX; 4189 4190 x.bv_val++; 4191 x.bv_len -= 2; 4192 4193 do { 4194 4195 /* eat leading spaces */ 4196 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4197 /* empty */; 4198 } 4199 4200 /* should be at issuer or serialNumber NamedValue */ 4201 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 4202 if ( have & HAVE_ISSUER ) { 4203 return LDAP_INVALID_SYNTAX; 4204 } 4205 4206 /* parse IssuerSerial */ 4207 x.bv_val += STRLENOF("issuer"); 4208 x.bv_len -= STRLENOF("issuer"); 4209 4210 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 4211 x.bv_val++; 4212 x.bv_len--; 4213 4214 /* eat leading spaces */ 4215 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4216 /* empty */; 4217 } 4218 4219 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4220 x.bv_val++; 4221 x.bv_len--; 4222 4223 /* eat leading spaces */ 4224 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4225 /* empty */; 4226 } 4227 4228 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) { 4229 return LDAP_INVALID_SYNTAX; 4230 } 4231 x.bv_val += STRLENOF("baseCertificateID "); 4232 x.bv_len -= STRLENOF("baseCertificateID "); 4233 4234 /* eat leading spaces */ 4235 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4236 /* empty */; 4237 } 4238 4239 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4240 x.bv_val++; 4241 x.bv_len--; 4242 4243 do { 4244 /* eat leading spaces */ 4245 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4246 /* empty */; 4247 } 4248 4249 /* parse issuer of baseCertificateID */ 4250 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) { 4251 if ( have2 & HAVE_ISSUER ) { 4252 return LDAP_INVALID_SYNTAX; 4253 } 4254 4255 x.bv_val += STRLENOF("issuer "); 4256 x.bv_len -= STRLENOF("issuer "); 4257 4258 /* eat leading spaces */ 4259 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4260 /* empty */; 4261 } 4262 4263 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4264 x.bv_val++; 4265 x.bv_len--; 4266 4267 /* eat leading spaces */ 4268 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4269 /* empty */; 4270 } 4271 4272 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) { 4273 return LDAP_INVALID_SYNTAX; 4274 } 4275 x.bv_val += STRLENOF("directoryName:rdnSequence:"); 4276 x.bv_len -= STRLENOF("directoryName:rdnSequence:"); 4277 4278 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 4279 x.bv_val++; 4280 x.bv_len--; 4281 4282 is->bv_val = x.bv_val; 4283 is->bv_len = 0; 4284 4285 for ( ; is->bv_len < x.bv_len; ) { 4286 if ( is->bv_val[is->bv_len] != '"' ) { 4287 is->bv_len++; 4288 continue; 4289 } 4290 if ( is->bv_val[is->bv_len + 1] == '"' ) { 4291 /* double dquote */ 4292 is->bv_len += 2; 4293 continue; 4294 } 4295 break; 4296 } 4297 x.bv_val += is->bv_len + 1; 4298 x.bv_len -= is->bv_len + 1; 4299 4300 /* eat leading spaces */ 4301 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4302 /* empty */; 4303 } 4304 4305 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4306 x.bv_val++; 4307 x.bv_len--; 4308 4309 have2 |= HAVE_ISSUER; 4310 4311 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) { 4312 if ( have2 & HAVE_SN ) { 4313 return LDAP_INVALID_SYNTAX; 4314 } 4315 4316 x.bv_val += STRLENOF("serial "); 4317 x.bv_len -= STRLENOF("serial "); 4318 4319 /* eat leading spaces */ 4320 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 4321 /* empty */; 4322 } 4323 4324 if ( checkNum( &x, i_sn ) ) { 4325 return LDAP_INVALID_SYNTAX; 4326 } 4327 4328 x.bv_val += i_sn->bv_len; 4329 x.bv_len -= i_sn->bv_len; 4330 4331 have2 |= HAVE_SN; 4332 4333 } else { 4334 return LDAP_INVALID_SYNTAX; 4335 } 4336 4337 /* eat leading spaces */ 4338 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4339 /* empty */; 4340 } 4341 4342 if ( have2 == HAVE_ALL ) { 4343 break; 4344 } 4345 4346 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX; 4347 x.bv_val++; 4348 x.bv_len--; 4349 } while ( 1 ); 4350 4351 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4352 x.bv_val++; 4353 x.bv_len--; 4354 4355 /* eat leading spaces */ 4356 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4357 /* empty */; 4358 } 4359 4360 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4361 x.bv_val++; 4362 x.bv_len--; 4363 4364 have |= HAVE_ISSUER; 4365 4366 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) { 4367 if ( have & HAVE_SN ) { 4368 return LDAP_INVALID_SYNTAX; 4369 } 4370 4371 /* parse serialNumber */ 4372 x.bv_val += STRLENOF("serialNumber"); 4373 x.bv_len -= STRLENOF("serialNumber"); 4374 4375 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 4376 x.bv_val++; 4377 x.bv_len--; 4378 4379 /* eat leading spaces */ 4380 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4381 /* empty */; 4382 } 4383 4384 if ( checkNum( &x, sn ) ) { 4385 return LDAP_INVALID_SYNTAX; 4386 } 4387 4388 x.bv_val += sn->bv_len; 4389 x.bv_len -= sn->bv_len; 4390 4391 have |= HAVE_SN; 4392 4393 } else { 4394 return LDAP_INVALID_SYNTAX; 4395 } 4396 4397 /* eat spaces */ 4398 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4399 /* empty */; 4400 } 4401 4402 if ( have == HAVE_ALL ) { 4403 break; 4404 } 4405 4406 if ( x.bv_val[0] != ',' ) { 4407 return LDAP_INVALID_SYNTAX; 4408 } 4409 x.bv_val++ ; 4410 x.bv_len--; 4411 } while ( 1 ); 4412 4413 /* should have no characters left... */ 4414 if( x.bv_len ) return LDAP_INVALID_SYNTAX; 4415 4416 if ( numdquotes == 0 ) { 4417 ber_dupbv_x( &ni, is, ctx ); 4418 4419 } else { 4420 ber_len_t src, dst; 4421 4422 ni.bv_len = is->bv_len - numdquotes; 4423 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 4424 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 4425 if ( is->bv_val[src] == '"' ) { 4426 src++; 4427 } 4428 ni.bv_val[dst] = is->bv_val[src]; 4429 } 4430 ni.bv_val[dst] = '\0'; 4431 } 4432 4433 *is = ni; 4434 4435 /* need to handle double dquotes here */ 4436 return 0; 4437 } 4438 4439 /* X.509 PMI serialNumberAndIssuerSerialValidate */ 4440 static int 4441 serialNumberAndIssuerSerialValidate( 4442 Syntax *syntax, 4443 struct berval *in ) 4444 { 4445 int rc; 4446 struct berval sn, i, i_sn; 4447 4448 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n", 4449 in->bv_val, 0, 0 ); 4450 4451 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL ); 4452 if ( rc ) { 4453 goto done; 4454 } 4455 4456 /* validate DN -- doesn't handle double dquote */ 4457 rc = dnValidate( NULL, &i ); 4458 if ( rc ) { 4459 rc = LDAP_INVALID_SYNTAX; 4460 } 4461 4462 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4463 slap_sl_free( i.bv_val, NULL ); 4464 } 4465 4466 done:; 4467 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n", 4468 in->bv_val, rc, 0 ); 4469 4470 return rc; 4471 } 4472 4473 /* X.509 PMI serialNumberAndIssuerSerialPretty */ 4474 static int 4475 serialNumberAndIssuerSerialPretty( 4476 Syntax *syntax, 4477 struct berval *in, 4478 struct berval *out, 4479 void *ctx ) 4480 { 4481 struct berval sn, i, i_sn, ni = BER_BVNULL; 4482 char *p; 4483 int rc; 4484 4485 assert( in != NULL ); 4486 assert( out != NULL ); 4487 4488 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n", 4489 in->bv_val, 0, 0 ); 4490 4491 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx ); 4492 if ( rc ) { 4493 goto done; 4494 } 4495 4496 rc = dnPretty( syntax, &i, &ni, ctx ); 4497 4498 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4499 slap_sl_free( i.bv_val, ctx ); 4500 } 4501 4502 if ( rc ) { 4503 rc = LDAP_INVALID_SYNTAX; 4504 goto done; 4505 } 4506 4507 /* make room from sn + "$" */ 4508 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }") 4509 + sn.bv_len + ni.bv_len + i_sn.bv_len; 4510 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4511 4512 if ( out->bv_val == NULL ) { 4513 out->bv_len = 0; 4514 rc = LDAP_OTHER; 4515 goto done; 4516 } 4517 4518 p = out->bv_val; 4519 p = lutil_strcopy( p, "{ serialNumber " ); 4520 p = lutil_strbvcopy( p, &sn ); 4521 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4522 p = lutil_strbvcopy( p, &ni ); 4523 p = lutil_strcopy( p, "\" }, serial " ); 4524 p = lutil_strbvcopy( p, &i_sn ); 4525 p = lutil_strcopy( p, " } } }" ); 4526 4527 assert( p == &out->bv_val[out->bv_len] ); 4528 4529 done:; 4530 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n", 4531 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4532 4533 slap_sl_free( ni.bv_val, ctx ); 4534 4535 return rc; 4536 } 4537 4538 /* X.509 PMI serialNumberAndIssuerSerialNormalize */ 4539 /* 4540 * This routine is called by attributeCertificateExactNormalize 4541 * when attributeCertificateExactNormalize receives a search 4542 * string instead of a attribute certificate. This routine 4543 * checks if the search value is valid and then returns the 4544 * normalized value 4545 */ 4546 static int 4547 serialNumberAndIssuerSerialNormalize( 4548 slap_mask_t usage, 4549 Syntax *syntax, 4550 MatchingRule *mr, 4551 struct berval *in, 4552 struct berval *out, 4553 void *ctx ) 4554 { 4555 struct berval i, ni = BER_BVNULL, 4556 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL, 4557 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL; 4558 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN], 4559 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN]; 4560 char *p; 4561 int rc; 4562 4563 assert( in != NULL ); 4564 assert( out != NULL ); 4565 4566 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n", 4567 in->bv_val, 0, 0 ); 4568 4569 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx ); 4570 if ( rc ) { 4571 goto func_leave; 4572 } 4573 4574 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 4575 4576 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4577 slap_sl_free( i.bv_val, ctx ); 4578 } 4579 4580 if ( rc ) { 4581 rc = LDAP_INVALID_SYNTAX; 4582 goto func_leave; 4583 } 4584 4585 /* Convert sn to canonical hex */ 4586 sn2.bv_val = sbuf2; 4587 sn2.bv_len = sn.bv_len; 4588 if ( sn.bv_len > sizeof( sbuf2 ) ) { 4589 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx ); 4590 } 4591 if ( lutil_str2bin( &sn, &sn2, ctx ) ) { 4592 rc = LDAP_INVALID_SYNTAX; 4593 goto func_leave; 4594 } 4595 4596 /* Convert i_sn to canonical hex */ 4597 i_sn2.bv_val = i_sbuf2; 4598 i_sn2.bv_len = i_sn.bv_len; 4599 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) { 4600 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx ); 4601 } 4602 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) { 4603 rc = LDAP_INVALID_SYNTAX; 4604 goto func_leave; 4605 } 4606 4607 sn3.bv_val = sbuf3; 4608 sn3.bv_len = sizeof(sbuf3); 4609 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) { 4610 rc = LDAP_INVALID_SYNTAX; 4611 goto func_leave; 4612 } 4613 4614 i_sn3.bv_val = i_sbuf3; 4615 i_sn3.bv_len = sizeof(i_sbuf3); 4616 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) { 4617 rc = LDAP_INVALID_SYNTAX; 4618 goto func_leave; 4619 } 4620 4621 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }") 4622 + sn3.bv_len + ni.bv_len + i_sn3.bv_len; 4623 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4624 4625 if ( out->bv_val == NULL ) { 4626 out->bv_len = 0; 4627 rc = LDAP_OTHER; 4628 goto func_leave; 4629 } 4630 4631 p = out->bv_val; 4632 4633 p = lutil_strcopy( p, "{ serialNumber " ); 4634 p = lutil_strbvcopy( p, &sn3 ); 4635 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4636 p = lutil_strbvcopy( p, &ni ); 4637 p = lutil_strcopy( p, "\" }, serial " ); 4638 p = lutil_strbvcopy( p, &i_sn3 ); 4639 p = lutil_strcopy( p, " } } }" ); 4640 4641 assert( p == &out->bv_val[out->bv_len] ); 4642 4643 func_leave: 4644 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n", 4645 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4646 4647 if ( sn2.bv_val != sbuf2 ) { 4648 slap_sl_free( sn2.bv_val, ctx ); 4649 } 4650 4651 if ( i_sn2.bv_val != i_sbuf2 ) { 4652 slap_sl_free( i_sn2.bv_val, ctx ); 4653 } 4654 4655 if ( sn3.bv_val != sbuf3 ) { 4656 slap_sl_free( sn3.bv_val, ctx ); 4657 } 4658 4659 if ( i_sn3.bv_val != i_sbuf3 ) { 4660 slap_sl_free( i_sn3.bv_val, ctx ); 4661 } 4662 4663 slap_sl_free( ni.bv_val, ctx ); 4664 4665 return rc; 4666 } 4667 4668 /* X.509 PMI attributeCertificateExactNormalize */ 4669 static int 4670 attributeCertificateExactNormalize( 4671 slap_mask_t usage, 4672 Syntax *syntax, 4673 MatchingRule *mr, 4674 struct berval *val, 4675 struct berval *normalized, 4676 void *ctx ) 4677 { 4678 BerElementBuffer berbuf; 4679 BerElement *ber = (BerElement *)&berbuf; 4680 ber_tag_t tag; 4681 ber_len_t len; 4682 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN]; 4683 struct berval sn, i_sn, sn2, i_sn2; 4684 struct berval issuer_dn = BER_BVNULL, bvdn; 4685 char *p; 4686 int rc = LDAP_INVALID_SYNTAX; 4687 4688 if ( BER_BVISEMPTY( val ) ) { 4689 goto done; 4690 } 4691 4692 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 4693 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx ); 4694 } 4695 4696 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 4697 4698 ber_init2( ber, val, LBER_USE_DER ); 4699 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 4700 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4701 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */ 4702 ber_skip_data( ber, len ); 4703 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */ 4704 ber_skip_data( ber, len ); 4705 4706 /* Issuer */ 4707 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4708 /* issuerName (GeneralNames sequence; optional)? */ 4709 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */ 4710 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */ 4711 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */ 4712 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) { 4713 rc = LDAP_INVALID_SYNTAX; 4714 goto done; 4715 } 4716 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */ 4717 len = ber_ptrlen( ber ); 4718 bvdn.bv_val = val->bv_val + len; 4719 bvdn.bv_len = val->bv_len - len; 4720 rc = dnX509normalize( &bvdn, &issuer_dn ); 4721 if ( rc != LDAP_SUCCESS ) goto done; 4722 4723 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */ 4724 ber_skip_data( ber, len ); 4725 tag = ber_skip_tag( ber, &len ); /* serial number */ 4726 if ( tag != LBER_INTEGER ) { 4727 rc = LDAP_INVALID_SYNTAX; 4728 goto done; 4729 } 4730 i_sn.bv_val = (char *)ber->ber_ptr; 4731 i_sn.bv_len = len; 4732 i_sn2.bv_val = issuer_serialbuf; 4733 i_sn2.bv_len = sizeof(issuer_serialbuf); 4734 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) { 4735 rc = LDAP_INVALID_SYNTAX; 4736 goto done; 4737 } 4738 ber_skip_data( ber, len ); 4739 4740 /* issuerUID (bitstring; optional)? */ 4741 /* objectDigestInfo (sequence; optional)? */ 4742 4743 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */ 4744 ber_skip_data( ber, len ); 4745 tag = ber_skip_tag( ber, &len ); /* serial number */ 4746 if ( tag != LBER_INTEGER ) { 4747 rc = LDAP_INVALID_SYNTAX; 4748 goto done; 4749 } 4750 sn.bv_val = (char *)ber->ber_ptr; 4751 sn.bv_len = len; 4752 sn2.bv_val = serialbuf; 4753 sn2.bv_len = sizeof(serialbuf); 4754 if ( slap_bin2hex( &sn, &sn2, ctx ) ) { 4755 rc = LDAP_INVALID_SYNTAX; 4756 goto done; 4757 } 4758 ber_skip_data( ber, len ); 4759 4760 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" ) 4761 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len; 4762 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 4763 4764 p = normalized->bv_val; 4765 4766 p = lutil_strcopy( p, "{ serialNumber " ); 4767 p = lutil_strbvcopy( p, &sn2 ); 4768 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4769 p = lutil_strbvcopy( p, &issuer_dn ); 4770 p = lutil_strcopy( p, "\" }, serial " ); 4771 p = lutil_strbvcopy( p, &i_sn2 ); 4772 p = lutil_strcopy( p, " } } }" ); 4773 4774 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n", 4775 normalized->bv_val, NULL, NULL ); 4776 4777 rc = LDAP_SUCCESS; 4778 4779 done: 4780 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 4781 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx ); 4782 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx ); 4783 4784 return rc; 4785 } 4786 4787 4788 static int 4789 hexValidate( 4790 Syntax *syntax, 4791 struct berval *in ) 4792 { 4793 ber_len_t i; 4794 4795 assert( in != NULL ); 4796 assert( !BER_BVISNULL( in ) ); 4797 4798 for ( i = 0; i < in->bv_len; i++ ) { 4799 if ( !ASCII_HEX( in->bv_val[ i ] ) ) { 4800 return LDAP_INVALID_SYNTAX; 4801 } 4802 } 4803 4804 return LDAP_SUCCESS; 4805 } 4806 4807 /* Normalize a SID as used inside a CSN: 4808 * three-digit numeric string */ 4809 static int 4810 hexNormalize( 4811 slap_mask_t usage, 4812 Syntax *syntax, 4813 MatchingRule *mr, 4814 struct berval *val, 4815 struct berval *normalized, 4816 void *ctx ) 4817 { 4818 ber_len_t i; 4819 4820 assert( val != NULL ); 4821 assert( normalized != NULL ); 4822 4823 ber_dupbv_x( normalized, val, ctx ); 4824 4825 for ( i = 0; i < normalized->bv_len; i++ ) { 4826 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) { 4827 ber_memfree_x( normalized->bv_val, ctx ); 4828 BER_BVZERO( normalized ); 4829 return LDAP_INVALID_SYNTAX; 4830 } 4831 4832 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 4833 } 4834 4835 return LDAP_SUCCESS; 4836 } 4837 4838 static int 4839 sidValidate ( 4840 Syntax *syntax, 4841 struct berval *in ) 4842 { 4843 assert( in != NULL ); 4844 assert( !BER_BVISNULL( in ) ); 4845 4846 if ( in->bv_len != 3 ) { 4847 return LDAP_INVALID_SYNTAX; 4848 } 4849 4850 return hexValidate( NULL, in ); 4851 } 4852 4853 /* Normalize a SID as used inside a CSN: 4854 * three-digit numeric string */ 4855 static int 4856 sidNormalize( 4857 slap_mask_t usage, 4858 Syntax *syntax, 4859 MatchingRule *mr, 4860 struct berval *val, 4861 struct berval *normalized, 4862 void *ctx ) 4863 { 4864 if ( val->bv_len != 3 ) { 4865 return LDAP_INVALID_SYNTAX; 4866 } 4867 4868 return hexNormalize( 0, NULL, NULL, val, normalized, ctx ); 4869 } 4870 4871 static int 4872 sidPretty( 4873 Syntax *syntax, 4874 struct berval *val, 4875 struct berval *out, 4876 void *ctx ) 4877 { 4878 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 4879 } 4880 4881 /* Normalize a SID as used inside a CSN, either as-is 4882 * (assertion value) or extracted from the CSN 4883 * (attribute value) */ 4884 static int 4885 csnSidNormalize( 4886 slap_mask_t usage, 4887 Syntax *syntax, 4888 MatchingRule *mr, 4889 struct berval *val, 4890 struct berval *normalized, 4891 void *ctx ) 4892 { 4893 struct berval bv; 4894 char *ptr, 4895 buf[ 4 ]; 4896 4897 4898 if ( BER_BVISEMPTY( val ) ) { 4899 return LDAP_INVALID_SYNTAX; 4900 } 4901 4902 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 4903 return sidNormalize( 0, NULL, NULL, val, normalized, ctx ); 4904 } 4905 4906 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 4907 4908 ptr = ber_bvchr( val, '#' ); 4909 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 4910 return LDAP_INVALID_SYNTAX; 4911 } 4912 4913 bv.bv_val = ptr + 1; 4914 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 4915 4916 ptr = ber_bvchr( &bv, '#' ); 4917 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 4918 return LDAP_INVALID_SYNTAX; 4919 } 4920 4921 bv.bv_val = ptr + 1; 4922 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 4923 4924 ptr = ber_bvchr( &bv, '#' ); 4925 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 4926 return LDAP_INVALID_SYNTAX; 4927 } 4928 4929 bv.bv_len = ptr - bv.bv_val; 4930 4931 if ( bv.bv_len == 2 ) { 4932 /* OpenLDAP 2.3 SID */ 4933 buf[ 0 ] = '0'; 4934 buf[ 1 ] = bv.bv_val[ 0 ]; 4935 buf[ 2 ] = bv.bv_val[ 1 ]; 4936 buf[ 3 ] = '\0'; 4937 4938 bv.bv_val = buf; 4939 bv.bv_len = 3; 4940 } 4941 4942 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx ); 4943 } 4944 4945 static int 4946 csnValidate( 4947 Syntax *syntax, 4948 struct berval *in ) 4949 { 4950 struct berval bv; 4951 char *ptr; 4952 int rc; 4953 4954 assert( in != NULL ); 4955 assert( !BER_BVISNULL( in ) ); 4956 4957 if ( BER_BVISEMPTY( in ) ) { 4958 return LDAP_INVALID_SYNTAX; 4959 } 4960 4961 bv = *in; 4962 4963 ptr = ber_bvchr( &bv, '#' ); 4964 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) { 4965 return LDAP_INVALID_SYNTAX; 4966 } 4967 4968 bv.bv_len = ptr - bv.bv_val; 4969 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) && 4970 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) 4971 { 4972 return LDAP_INVALID_SYNTAX; 4973 } 4974 4975 rc = generalizedTimeValidate( NULL, &bv ); 4976 if ( rc != LDAP_SUCCESS ) { 4977 return rc; 4978 } 4979 4980 bv.bv_val = ptr + 1; 4981 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 4982 4983 ptr = ber_bvchr( &bv, '#' ); 4984 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) { 4985 return LDAP_INVALID_SYNTAX; 4986 } 4987 4988 bv.bv_len = ptr - bv.bv_val; 4989 if ( bv.bv_len != 6 ) { 4990 return LDAP_INVALID_SYNTAX; 4991 } 4992 4993 rc = hexValidate( NULL, &bv ); 4994 if ( rc != LDAP_SUCCESS ) { 4995 return rc; 4996 } 4997 4998 bv.bv_val = ptr + 1; 4999 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 5000 5001 ptr = ber_bvchr( &bv, '#' ); 5002 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) { 5003 return LDAP_INVALID_SYNTAX; 5004 } 5005 5006 bv.bv_len = ptr - bv.bv_val; 5007 if ( bv.bv_len == 2 ) { 5008 /* tolerate old 2-digit replica-id */ 5009 rc = hexValidate( NULL, &bv ); 5010 5011 } else { 5012 rc = sidValidate( NULL, &bv ); 5013 } 5014 if ( rc != LDAP_SUCCESS ) { 5015 return rc; 5016 } 5017 5018 bv.bv_val = ptr + 1; 5019 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 5020 5021 if ( bv.bv_len != 6 ) { 5022 return LDAP_INVALID_SYNTAX; 5023 } 5024 5025 return hexValidate( NULL, &bv ); 5026 } 5027 5028 /* Normalize a CSN in OpenLDAP 2.1 format */ 5029 static int 5030 csnNormalize21( 5031 slap_mask_t usage, 5032 Syntax *syntax, 5033 MatchingRule *mr, 5034 struct berval *val, 5035 struct berval *normalized, 5036 void *ctx ) 5037 { 5038 struct berval gt, cnt, sid, mod; 5039 struct berval bv; 5040 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 5041 char *ptr; 5042 ber_len_t i; 5043 5044 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5045 assert( !BER_BVISEMPTY( val ) ); 5046 5047 gt = *val; 5048 5049 ptr = ber_bvchr( >, '#' ); 5050 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) { 5051 return LDAP_INVALID_SYNTAX; 5052 } 5053 5054 gt.bv_len = ptr - gt.bv_val; 5055 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) { 5056 return LDAP_INVALID_SYNTAX; 5057 } 5058 5059 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) { 5060 return LDAP_INVALID_SYNTAX; 5061 } 5062 5063 cnt.bv_val = ptr + 1; 5064 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5065 5066 ptr = ber_bvchr( &cnt, '#' ); 5067 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5068 return LDAP_INVALID_SYNTAX; 5069 } 5070 5071 cnt.bv_len = ptr - cnt.bv_val; 5072 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) { 5073 return LDAP_INVALID_SYNTAX; 5074 } 5075 5076 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) { 5077 return LDAP_INVALID_SYNTAX; 5078 } 5079 5080 cnt.bv_val += STRLENOF( "0x" ); 5081 cnt.bv_len -= STRLENOF( "0x" ); 5082 5083 sid.bv_val = ptr + 1; 5084 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5085 5086 ptr = ber_bvchr( &sid, '#' ); 5087 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5088 return LDAP_INVALID_SYNTAX; 5089 } 5090 5091 sid.bv_len = ptr - sid.bv_val; 5092 if ( sid.bv_len != STRLENOF( "0" ) ) { 5093 return LDAP_INVALID_SYNTAX; 5094 } 5095 5096 mod.bv_val = ptr + 1; 5097 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5098 if ( mod.bv_len != STRLENOF( "0000" ) ) { 5099 return LDAP_INVALID_SYNTAX; 5100 } 5101 5102 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 5103 bv.bv_val = buf; 5104 5105 ptr = bv.bv_val; 5106 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) ); 5107 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ], 5108 STRLENOF( "MM" ) ); 5109 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ], 5110 STRLENOF( "SS" ) ); 5111 ptr = lutil_strcopy( ptr, ".000000Z#00" ); 5112 ptr = lutil_strbvcopy( ptr, &cnt ); 5113 *ptr++ = '#'; 5114 *ptr++ = '0'; 5115 *ptr++ = '0'; 5116 *ptr++ = sid.bv_val[ 0 ]; 5117 *ptr++ = '#'; 5118 *ptr++ = '0'; 5119 *ptr++ = '0'; 5120 for ( i = 0; i < mod.bv_len; i++ ) { 5121 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 5122 } 5123 *ptr = '\0'; 5124 5125 assert( ptr == &bv.bv_val[bv.bv_len] ); 5126 5127 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 5128 return LDAP_INVALID_SYNTAX; 5129 } 5130 5131 ber_dupbv_x( normalized, &bv, ctx ); 5132 5133 return LDAP_SUCCESS; 5134 } 5135 5136 /* Normalize a CSN in OpenLDAP 2.3 format */ 5137 static int 5138 csnNormalize23( 5139 slap_mask_t usage, 5140 Syntax *syntax, 5141 MatchingRule *mr, 5142 struct berval *val, 5143 struct berval *normalized, 5144 void *ctx ) 5145 { 5146 struct berval gt, cnt, sid, mod; 5147 struct berval bv; 5148 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 5149 char *ptr; 5150 ber_len_t i; 5151 5152 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5153 assert( !BER_BVISEMPTY( val ) ); 5154 5155 gt = *val; 5156 5157 ptr = ber_bvchr( >, '#' ); 5158 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) { 5159 return LDAP_INVALID_SYNTAX; 5160 } 5161 5162 gt.bv_len = ptr - gt.bv_val; 5163 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 5164 return LDAP_INVALID_SYNTAX; 5165 } 5166 5167 cnt.bv_val = ptr + 1; 5168 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5169 5170 ptr = ber_bvchr( &cnt, '#' ); 5171 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5172 return LDAP_INVALID_SYNTAX; 5173 } 5174 5175 cnt.bv_len = ptr - cnt.bv_val; 5176 if ( cnt.bv_len != STRLENOF( "000000" ) ) { 5177 return LDAP_INVALID_SYNTAX; 5178 } 5179 5180 sid.bv_val = ptr + 1; 5181 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5182 5183 ptr = ber_bvchr( &sid, '#' ); 5184 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5185 return LDAP_INVALID_SYNTAX; 5186 } 5187 5188 sid.bv_len = ptr - sid.bv_val; 5189 if ( sid.bv_len != STRLENOF( "00" ) ) { 5190 return LDAP_INVALID_SYNTAX; 5191 } 5192 5193 mod.bv_val = ptr + 1; 5194 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5195 if ( mod.bv_len != STRLENOF( "000000" ) ) { 5196 return LDAP_INVALID_SYNTAX; 5197 } 5198 5199 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 5200 bv.bv_val = buf; 5201 5202 ptr = bv.bv_val; 5203 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 ); 5204 ptr = lutil_strcopy( ptr, ".000000Z#" ); 5205 ptr = lutil_strbvcopy( ptr, &cnt ); 5206 *ptr++ = '#'; 5207 *ptr++ = '0'; 5208 for ( i = 0; i < sid.bv_len; i++ ) { 5209 *ptr++ = TOLOWER( sid.bv_val[ i ] ); 5210 } 5211 *ptr++ = '#'; 5212 for ( i = 0; i < mod.bv_len; i++ ) { 5213 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 5214 } 5215 *ptr = '\0'; 5216 5217 assert( ptr == &bv.bv_val[bv.bv_len] ); 5218 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 5219 return LDAP_INVALID_SYNTAX; 5220 } 5221 5222 ber_dupbv_x( normalized, &bv, ctx ); 5223 5224 return LDAP_SUCCESS; 5225 } 5226 5227 /* Normalize a CSN */ 5228 static int 5229 csnNormalize( 5230 slap_mask_t usage, 5231 Syntax *syntax, 5232 MatchingRule *mr, 5233 struct berval *val, 5234 struct berval *normalized, 5235 void *ctx ) 5236 { 5237 struct berval cnt, sid, mod; 5238 char *ptr; 5239 ber_len_t i; 5240 5241 assert( val != NULL ); 5242 assert( normalized != NULL ); 5243 5244 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5245 5246 if ( BER_BVISEMPTY( val ) ) { 5247 return LDAP_INVALID_SYNTAX; 5248 } 5249 5250 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) { 5251 /* Openldap <= 2.3 */ 5252 5253 return csnNormalize23( usage, syntax, mr, val, normalized, ctx ); 5254 } 5255 5256 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) { 5257 /* Openldap 2.1 */ 5258 5259 return csnNormalize21( usage, syntax, mr, val, normalized, ctx ); 5260 } 5261 5262 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) { 5263 return LDAP_INVALID_SYNTAX; 5264 } 5265 5266 ptr = ber_bvchr( val, '#' ); 5267 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5268 return LDAP_INVALID_SYNTAX; 5269 } 5270 5271 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) { 5272 return LDAP_INVALID_SYNTAX; 5273 } 5274 5275 cnt.bv_val = ptr + 1; 5276 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5277 5278 ptr = ber_bvchr( &cnt, '#' ); 5279 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5280 return LDAP_INVALID_SYNTAX; 5281 } 5282 5283 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) { 5284 return LDAP_INVALID_SYNTAX; 5285 } 5286 5287 sid.bv_val = ptr + 1; 5288 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5289 5290 ptr = ber_bvchr( &sid, '#' ); 5291 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5292 return LDAP_INVALID_SYNTAX; 5293 } 5294 5295 sid.bv_len = ptr - sid.bv_val; 5296 if ( sid.bv_len != STRLENOF( "000" ) ) { 5297 return LDAP_INVALID_SYNTAX; 5298 } 5299 5300 mod.bv_val = ptr + 1; 5301 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5302 5303 if ( mod.bv_len != STRLENOF( "000000" ) ) { 5304 return LDAP_INVALID_SYNTAX; 5305 } 5306 5307 ber_dupbv_x( normalized, val, ctx ); 5308 5309 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" ); 5310 i < normalized->bv_len; i++ ) 5311 { 5312 /* assume it's already validated that's all hex digits */ 5313 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 5314 } 5315 5316 return LDAP_SUCCESS; 5317 } 5318 5319 static int 5320 csnPretty( 5321 Syntax *syntax, 5322 struct berval *val, 5323 struct berval *out, 5324 void *ctx ) 5325 { 5326 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 5327 } 5328 5329 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX 5330 /* slight optimization - does not need the start parameter */ 5331 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f) 5332 enum { start = 0 }; 5333 #endif 5334 5335 static int 5336 check_time_syntax (struct berval *val, 5337 int start, 5338 int *parts, 5339 struct berval *fraction) 5340 { 5341 /* 5342 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) 5343 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM] 5344 * GeneralizedTime supports leap seconds, UTCTime does not. 5345 */ 5346 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 }; 5347 static const int mdays[2][12] = { 5348 /* non-leap years */ 5349 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 5350 /* leap years */ 5351 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 5352 }; 5353 char *p, *e; 5354 int part, c, c1, c2, tzoffset, leapyear = 0; 5355 5356 p = val->bv_val; 5357 e = p + val->bv_len; 5358 5359 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 5360 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */ 5361 #endif 5362 for (part = start; part < 7 && p < e; part++) { 5363 c1 = *p; 5364 if (!ASCII_DIGIT(c1)) { 5365 break; 5366 } 5367 p++; 5368 if (p == e) { 5369 return LDAP_INVALID_SYNTAX; 5370 } 5371 c = *p++; 5372 if (!ASCII_DIGIT(c)) { 5373 return LDAP_INVALID_SYNTAX; 5374 } 5375 c += c1 * 10 - '0' * 11; 5376 if ((part | 1) == 3) { 5377 --c; 5378 if (c < 0) { 5379 return LDAP_INVALID_SYNTAX; 5380 } 5381 } 5382 if (c >= ceiling[part]) { 5383 if (! (c == 60 && part == 6 && start == 0)) 5384 return LDAP_INVALID_SYNTAX; 5385 } 5386 parts[part] = c; 5387 } 5388 if (part < 5 + start) { 5389 return LDAP_INVALID_SYNTAX; 5390 } 5391 for (; part < 9; part++) { 5392 parts[part] = 0; 5393 } 5394 5395 /* leapyear check for the Gregorian calendar (year>1581) */ 5396 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) { 5397 leapyear = 1; 5398 } 5399 5400 if (parts[3] >= mdays[leapyear][parts[2]]) { 5401 return LDAP_INVALID_SYNTAX; 5402 } 5403 5404 if (start == 0) { 5405 fraction->bv_val = p; 5406 fraction->bv_len = 0; 5407 if (p < e && (*p == '.' || *p == ',')) { 5408 char *end_num; 5409 while (++p < e && ASCII_DIGIT(*p)) { 5410 /* EMTPY */; 5411 } 5412 if (p - fraction->bv_val == 1) { 5413 return LDAP_INVALID_SYNTAX; 5414 } 5415 for (end_num = p; end_num[-1] == '0'; --end_num) { 5416 /* EMPTY */; 5417 } 5418 c = end_num - fraction->bv_val; 5419 if (c != 1) fraction->bv_len = c; 5420 } 5421 } 5422 5423 if (p == e) { 5424 /* no time zone */ 5425 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 5426 } 5427 5428 tzoffset = *p++; 5429 switch (tzoffset) { 5430 default: 5431 return LDAP_INVALID_SYNTAX; 5432 case 'Z': 5433 /* UTC */ 5434 break; 5435 case '+': 5436 case '-': 5437 for (part = 7; part < 9 && p < e; part++) { 5438 c1 = *p; 5439 if (!ASCII_DIGIT(c1)) { 5440 break; 5441 } 5442 p++; 5443 if (p == e) { 5444 return LDAP_INVALID_SYNTAX; 5445 } 5446 c2 = *p++; 5447 if (!ASCII_DIGIT(c2)) { 5448 return LDAP_INVALID_SYNTAX; 5449 } 5450 parts[part] = c1 * 10 + c2 - '0' * 11; 5451 if (parts[part] >= ceiling[part]) { 5452 return LDAP_INVALID_SYNTAX; 5453 } 5454 } 5455 if (part < 8 + start) { 5456 return LDAP_INVALID_SYNTAX; 5457 } 5458 5459 if (tzoffset == '-') { 5460 /* negative offset to UTC, ie west of Greenwich */ 5461 parts[4] += parts[7]; 5462 parts[5] += parts[8]; 5463 /* offset is just hhmm, no seconds */ 5464 for (part = 6; --part >= 0; ) { 5465 if (part != 3) { 5466 c = ceiling[part]; 5467 } else { 5468 c = mdays[leapyear][parts[2]]; 5469 } 5470 if (parts[part] >= c) { 5471 if (part == 0) { 5472 return LDAP_INVALID_SYNTAX; 5473 } 5474 parts[part] -= c; 5475 parts[part - 1]++; 5476 continue; 5477 } else if (part != 5) { 5478 break; 5479 } 5480 } 5481 } else { 5482 /* positive offset to UTC, ie east of Greenwich */ 5483 parts[4] -= parts[7]; 5484 parts[5] -= parts[8]; 5485 for (part = 6; --part >= 0; ) { 5486 if (parts[part] < 0) { 5487 if (part == 0) { 5488 return LDAP_INVALID_SYNTAX; 5489 } 5490 if (part != 3) { 5491 c = ceiling[part]; 5492 } else { 5493 /* make first arg to % non-negative */ 5494 c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; 5495 } 5496 parts[part] += c; 5497 parts[part - 1]--; 5498 continue; 5499 } else if (part != 5) { 5500 break; 5501 } 5502 } 5503 } 5504 } 5505 5506 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 5507 } 5508 5509 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 5510 5511 #if 0 5512 static int 5513 xutcTimeNormalize( 5514 Syntax *syntax, 5515 struct berval *val, 5516 struct berval *normalized ) 5517 { 5518 int parts[9], rc; 5519 5520 rc = check_time_syntax(val, 1, parts, NULL); 5521 if (rc != LDAP_SUCCESS) { 5522 return rc; 5523 } 5524 5525 normalized->bv_val = ch_malloc( 14 ); 5526 if ( normalized->bv_val == NULL ) { 5527 return LBER_ERROR_MEMORY; 5528 } 5529 5530 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ", 5531 parts[1], parts[2] + 1, parts[3] + 1, 5532 parts[4], parts[5], parts[6] ); 5533 normalized->bv_len = 13; 5534 5535 return LDAP_SUCCESS; 5536 } 5537 #endif /* 0 */ 5538 5539 static int 5540 utcTimeValidate( 5541 Syntax *syntax, 5542 struct berval *in ) 5543 { 5544 int parts[9]; 5545 return check_time_syntax(in, 1, parts, NULL); 5546 } 5547 5548 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ 5549 5550 static int 5551 generalizedTimeValidate( 5552 Syntax *syntax, 5553 struct berval *in ) 5554 { 5555 int parts[9]; 5556 struct berval fraction; 5557 return check_time_syntax(in, 0, parts, &fraction); 5558 } 5559 5560 static int 5561 generalizedTimeNormalize( 5562 slap_mask_t usage, 5563 Syntax *syntax, 5564 MatchingRule *mr, 5565 struct berval *val, 5566 struct berval *normalized, 5567 void *ctx ) 5568 { 5569 int parts[9], rc; 5570 unsigned int len; 5571 struct berval fraction; 5572 5573 rc = check_time_syntax(val, 0, parts, &fraction); 5574 if (rc != LDAP_SUCCESS) { 5575 return rc; 5576 } 5577 5578 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len; 5579 normalized->bv_val = slap_sl_malloc( len + 1, ctx ); 5580 if ( BER_BVISNULL( normalized ) ) { 5581 return LBER_ERROR_MEMORY; 5582 } 5583 5584 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d", 5585 parts[0], parts[1], parts[2] + 1, parts[3] + 1, 5586 parts[4], parts[5], parts[6] ); 5587 if ( !BER_BVISEMPTY( &fraction ) ) { 5588 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1, 5589 fraction.bv_val, fraction.bv_len ); 5590 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.'; 5591 } 5592 strcpy( normalized->bv_val + len-1, "Z" ); 5593 normalized->bv_len = len; 5594 5595 return LDAP_SUCCESS; 5596 } 5597 5598 static int 5599 generalizedTimeOrderingMatch( 5600 int *matchp, 5601 slap_mask_t flags, 5602 Syntax *syntax, 5603 MatchingRule *mr, 5604 struct berval *value, 5605 void *assertedValue ) 5606 { 5607 struct berval *asserted = (struct berval *) assertedValue; 5608 ber_len_t v_len = value->bv_len; 5609 ber_len_t av_len = asserted->bv_len; 5610 5611 /* ignore trailing 'Z' when comparing */ 5612 int match = memcmp( value->bv_val, asserted->bv_val, 5613 (v_len < av_len ? v_len : av_len) - 1 ); 5614 if ( match == 0 ) match = v_len - av_len; 5615 5616 *matchp = match; 5617 return LDAP_SUCCESS; 5618 } 5619 5620 /* Index generation function */ 5621 int generalizedTimeIndexer( 5622 slap_mask_t use, 5623 slap_mask_t flags, 5624 Syntax *syntax, 5625 MatchingRule *mr, 5626 struct berval *prefix, 5627 BerVarray values, 5628 BerVarray *keysp, 5629 void *ctx ) 5630 { 5631 int i, j; 5632 BerVarray keys; 5633 char tmp[5]; 5634 BerValue bvtmp; /* 40 bit index */ 5635 struct lutil_tm tm; 5636 struct lutil_timet tt; 5637 5638 bvtmp.bv_len = sizeof(tmp); 5639 bvtmp.bv_val = tmp; 5640 for( i=0; values[i].bv_val != NULL; i++ ) { 5641 /* just count them */ 5642 } 5643 5644 /* we should have at least one value at this point */ 5645 assert( i > 0 ); 5646 5647 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 5648 5649 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 5650 for( i=0, j=0; values[i].bv_val != NULL; i++ ) { 5651 assert(values[i].bv_val != NULL && values[i].bv_len >= 10); 5652 /* Use 40 bits of time for key */ 5653 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) { 5654 lutil_tm2time( &tm, &tt ); 5655 tmp[0] = tt.tt_gsec & 0xff; 5656 tmp[4] = tt.tt_sec & 0xff; 5657 tt.tt_sec >>= 8; 5658 tmp[3] = tt.tt_sec & 0xff; 5659 tt.tt_sec >>= 8; 5660 tmp[2] = tt.tt_sec & 0xff; 5661 tt.tt_sec >>= 8; 5662 tmp[1] = tt.tt_sec & 0xff; 5663 5664 ber_dupbv_x(&keys[j++], &bvtmp, ctx ); 5665 } 5666 } 5667 5668 keys[j].bv_val = NULL; 5669 keys[j].bv_len = 0; 5670 5671 *keysp = keys; 5672 5673 return LDAP_SUCCESS; 5674 } 5675 5676 /* Index generation function */ 5677 int generalizedTimeFilter( 5678 slap_mask_t use, 5679 slap_mask_t flags, 5680 Syntax *syntax, 5681 MatchingRule *mr, 5682 struct berval *prefix, 5683 void * assertedValue, 5684 BerVarray *keysp, 5685 void *ctx ) 5686 { 5687 BerVarray keys; 5688 char tmp[5]; 5689 BerValue bvtmp; /* 40 bit index */ 5690 BerValue *value = (BerValue *) assertedValue; 5691 struct lutil_tm tm; 5692 struct lutil_timet tt; 5693 5694 bvtmp.bv_len = sizeof(tmp); 5695 bvtmp.bv_val = tmp; 5696 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 5697 /* Use 40 bits of time for key */ 5698 if ( value->bv_val && value->bv_len >= 10 && 5699 lutil_parsetime( value->bv_val, &tm ) == 0 ) { 5700 5701 lutil_tm2time( &tm, &tt ); 5702 tmp[0] = tt.tt_gsec & 0xff; 5703 tmp[4] = tt.tt_sec & 0xff; 5704 tt.tt_sec >>= 8; 5705 tmp[3] = tt.tt_sec & 0xff; 5706 tt.tt_sec >>= 8; 5707 tmp[2] = tt.tt_sec & 0xff; 5708 tt.tt_sec >>= 8; 5709 tmp[1] = tt.tt_sec & 0xff; 5710 5711 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 5712 ber_dupbv_x(keys, &bvtmp, ctx ); 5713 keys[1].bv_val = NULL; 5714 keys[1].bv_len = 0; 5715 } else { 5716 keys = NULL; 5717 } 5718 5719 *keysp = keys; 5720 5721 return LDAP_SUCCESS; 5722 } 5723 5724 static int 5725 deliveryMethodValidate( 5726 Syntax *syntax, 5727 struct berval *val ) 5728 { 5729 #undef LENOF 5730 #define LENOF(s) (sizeof(s)-1) 5731 struct berval tmp = *val; 5732 /* 5733 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod ) 5734 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" / 5735 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone" 5736 */ 5737 again: 5738 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX; 5739 5740 switch( tmp.bv_val[0] ) { 5741 case 'a': 5742 case 'A': 5743 if(( tmp.bv_len >= LENOF("any") ) && 5744 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 )) 5745 { 5746 tmp.bv_len -= LENOF("any"); 5747 tmp.bv_val += LENOF("any"); 5748 break; 5749 } 5750 return LDAP_INVALID_SYNTAX; 5751 5752 case 'm': 5753 case 'M': 5754 if(( tmp.bv_len >= LENOF("mhs") ) && 5755 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 )) 5756 { 5757 tmp.bv_len -= LENOF("mhs"); 5758 tmp.bv_val += LENOF("mhs"); 5759 break; 5760 } 5761 return LDAP_INVALID_SYNTAX; 5762 5763 case 'p': 5764 case 'P': 5765 if(( tmp.bv_len >= LENOF("physical") ) && 5766 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 )) 5767 { 5768 tmp.bv_len -= LENOF("physical"); 5769 tmp.bv_val += LENOF("physical"); 5770 break; 5771 } 5772 return LDAP_INVALID_SYNTAX; 5773 5774 case 't': 5775 case 'T': /* telex or teletex or telephone */ 5776 if(( tmp.bv_len >= LENOF("telex") ) && 5777 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 )) 5778 { 5779 tmp.bv_len -= LENOF("telex"); 5780 tmp.bv_val += LENOF("telex"); 5781 break; 5782 } 5783 if(( tmp.bv_len >= LENOF("teletex") ) && 5784 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 )) 5785 { 5786 tmp.bv_len -= LENOF("teletex"); 5787 tmp.bv_val += LENOF("teletex"); 5788 break; 5789 } 5790 if(( tmp.bv_len >= LENOF("telephone") ) && 5791 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 )) 5792 { 5793 tmp.bv_len -= LENOF("telephone"); 5794 tmp.bv_val += LENOF("telephone"); 5795 break; 5796 } 5797 return LDAP_INVALID_SYNTAX; 5798 5799 case 'g': 5800 case 'G': /* g3fax or g4fax */ 5801 if(( tmp.bv_len >= LENOF("g3fax") ) && ( 5802 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) || 5803 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 ))) 5804 { 5805 tmp.bv_len -= LENOF("g3fax"); 5806 tmp.bv_val += LENOF("g3fax"); 5807 break; 5808 } 5809 return LDAP_INVALID_SYNTAX; 5810 5811 case 'i': 5812 case 'I': 5813 if(( tmp.bv_len >= LENOF("ia5") ) && 5814 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 )) 5815 { 5816 tmp.bv_len -= LENOF("ia5"); 5817 tmp.bv_val += LENOF("ia5"); 5818 break; 5819 } 5820 return LDAP_INVALID_SYNTAX; 5821 5822 case 'v': 5823 case 'V': 5824 if(( tmp.bv_len >= LENOF("videotex") ) && 5825 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 )) 5826 { 5827 tmp.bv_len -= LENOF("videotex"); 5828 tmp.bv_val += LENOF("videotex"); 5829 break; 5830 } 5831 return LDAP_INVALID_SYNTAX; 5832 5833 default: 5834 return LDAP_INVALID_SYNTAX; 5835 } 5836 5837 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS; 5838 5839 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 5840 tmp.bv_len++; 5841 tmp.bv_val--; 5842 } 5843 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) { 5844 tmp.bv_len++; 5845 tmp.bv_val--; 5846 } else { 5847 return LDAP_INVALID_SYNTAX; 5848 } 5849 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 5850 tmp.bv_len++; 5851 tmp.bv_val--; 5852 } 5853 5854 goto again; 5855 } 5856 5857 static int 5858 nisNetgroupTripleValidate( 5859 Syntax *syntax, 5860 struct berval *val ) 5861 { 5862 char *p, *e; 5863 int commas = 0; 5864 5865 if ( BER_BVISEMPTY( val ) ) { 5866 return LDAP_INVALID_SYNTAX; 5867 } 5868 5869 p = (char *)val->bv_val; 5870 e = p + val->bv_len; 5871 5872 if ( *p != '(' /*')'*/ ) { 5873 return LDAP_INVALID_SYNTAX; 5874 } 5875 5876 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) { 5877 if ( *p == ',' ) { 5878 commas++; 5879 if ( commas > 2 ) { 5880 return LDAP_INVALID_SYNTAX; 5881 } 5882 5883 } else if ( !AD_CHAR( *p ) ) { 5884 return LDAP_INVALID_SYNTAX; 5885 } 5886 } 5887 5888 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) { 5889 return LDAP_INVALID_SYNTAX; 5890 } 5891 5892 p++; 5893 5894 if (p != e) { 5895 return LDAP_INVALID_SYNTAX; 5896 } 5897 5898 return LDAP_SUCCESS; 5899 } 5900 5901 static int 5902 bootParameterValidate( 5903 Syntax *syntax, 5904 struct berval *val ) 5905 { 5906 char *p, *e; 5907 5908 if ( BER_BVISEMPTY( val ) ) { 5909 return LDAP_INVALID_SYNTAX; 5910 } 5911 5912 p = (char *)val->bv_val; 5913 e = p + val->bv_len; 5914 5915 /* key */ 5916 for (; ( p < e ) && ( *p != '=' ); p++ ) { 5917 if ( !AD_CHAR( *p ) ) { 5918 return LDAP_INVALID_SYNTAX; 5919 } 5920 } 5921 5922 if ( *p != '=' ) { 5923 return LDAP_INVALID_SYNTAX; 5924 } 5925 5926 /* server */ 5927 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) { 5928 if ( !AD_CHAR( *p ) ) { 5929 return LDAP_INVALID_SYNTAX; 5930 } 5931 } 5932 5933 if ( *p != ':' ) { 5934 return LDAP_INVALID_SYNTAX; 5935 } 5936 5937 /* path */ 5938 for ( p++; p < e; p++ ) { 5939 if ( !SLAP_PRINTABLE( *p ) ) { 5940 return LDAP_INVALID_SYNTAX; 5941 } 5942 } 5943 5944 return LDAP_SUCCESS; 5945 } 5946 5947 static int 5948 firstComponentNormalize( 5949 slap_mask_t usage, 5950 Syntax *syntax, 5951 MatchingRule *mr, 5952 struct berval *val, 5953 struct berval *normalized, 5954 void *ctx ) 5955 { 5956 int rc; 5957 struct berval comp; 5958 ber_len_t len; 5959 5960 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) { 5961 ber_dupbv_x( normalized, val, ctx ); 5962 return LDAP_SUCCESS; 5963 } 5964 5965 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 5966 5967 if( ! ( val->bv_val[0] == '(' /*')'*/ 5968 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' ) 5969 && ! ( val->bv_val[0] == '{' /*'}'*/ 5970 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) ) 5971 { 5972 return LDAP_INVALID_SYNTAX; 5973 } 5974 5975 /* trim leading white space */ 5976 for( len=1; 5977 len < val->bv_len && ASCII_SPACE(val->bv_val[len]); 5978 len++ ) 5979 { 5980 /* empty */ 5981 } 5982 5983 /* grab next word */ 5984 comp.bv_val = &val->bv_val[len]; 5985 len = val->bv_len - len - STRLENOF(/*"{"*/ "}"); 5986 for( comp.bv_len = 0; 5987 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len; 5988 comp.bv_len++ ) 5989 { 5990 /* empty */ 5991 } 5992 5993 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) { 5994 rc = numericoidValidate( NULL, &comp ); 5995 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) { 5996 rc = integerValidate( NULL, &comp ); 5997 } else { 5998 rc = LDAP_INVALID_SYNTAX; 5999 } 6000 6001 6002 if( rc == LDAP_SUCCESS ) { 6003 ber_dupbv_x( normalized, &comp, ctx ); 6004 } 6005 6006 return rc; 6007 } 6008 6009 static char *country_gen_syn[] = { 6010 "1.3.6.1.4.1.1466.115.121.1.15", 6011 "1.3.6.1.4.1.1466.115.121.1.26", 6012 "1.3.6.1.4.1.1466.115.121.1.44", 6013 NULL 6014 }; 6015 6016 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " 6017 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " 6018 6019 static slap_syntax_defs_rec syntax_defs[] = { 6020 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " 6021 X_BINARY X_NOT_H_R ")", 6022 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL}, 6023 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")", 6024 0, NULL, NULL, NULL}, 6025 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", 6026 0, NULL, NULL, NULL}, 6027 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " 6028 X_NOT_H_R ")", 6029 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 6030 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " 6031 X_NOT_H_R ")", 6032 SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 6033 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", 6034 0, NULL, bitStringValidate, NULL }, 6035 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", 6036 0, NULL, booleanValidate, NULL}, 6037 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " 6038 X_BINARY X_NOT_H_R ")", 6039 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6040 NULL, certificateValidate, NULL}, 6041 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " 6042 X_BINARY X_NOT_H_R ")", 6043 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6044 NULL, certificateListValidate, NULL}, 6045 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " 6046 X_BINARY X_NOT_H_R ")", 6047 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6048 NULL, sequenceValidate, NULL}, 6049 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' " 6050 X_BINARY X_NOT_H_R ")", 6051 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6052 NULL, attributeCertificateValidate, NULL}, 6053 #if 0 /* need to go __after__ printableString */ 6054 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 6055 0, "1.3.6.1.4.1.1466.115.121.1.44", 6056 countryStringValidate, NULL}, 6057 #endif 6058 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", 6059 0, NULL, dnValidate, dnPretty}, 6060 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )", 6061 0, NULL, rdnValidate, rdnPretty}, 6062 #ifdef LDAP_COMP_MATCH 6063 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", 6064 0, NULL, allComponentsValidate, NULL}, 6065 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ", 6066 0, NULL, componentFilterValidate, NULL}, 6067 #endif 6068 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )", 6069 0, NULL, NULL, NULL}, 6070 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", 6071 0, NULL, deliveryMethodValidate, NULL}, 6072 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", 6073 0, NULL, UTF8StringValidate, NULL}, 6074 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", 6075 0, NULL, NULL, NULL}, 6076 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", 6077 0, NULL, NULL, NULL}, 6078 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )", 6079 0, NULL, NULL, NULL}, 6080 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )", 6081 0, NULL, NULL, NULL}, 6082 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", 6083 0, NULL, NULL, NULL}, 6084 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", 6085 0, NULL, printablesStringValidate, NULL}, 6086 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")", 6087 SLAP_SYNTAX_BLOB, NULL, NULL, NULL}, 6088 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", 6089 0, NULL, generalizedTimeValidate, NULL}, 6090 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", 6091 0, NULL, NULL, NULL}, 6092 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", 6093 0, NULL, IA5StringValidate, NULL}, 6094 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", 6095 0, NULL, integerValidate, NULL}, 6096 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")", 6097 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 6098 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )", 6099 0, NULL, NULL, NULL}, 6100 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", 6101 0, NULL, NULL, NULL}, 6102 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", 6103 0, NULL, NULL, NULL}, 6104 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", 6105 0, NULL, NULL, NULL}, 6106 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", 6107 0, NULL, NULL, NULL}, 6108 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", 6109 0, NULL, nameUIDValidate, nameUIDPretty }, 6110 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", 6111 0, NULL, NULL, NULL}, 6112 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", 6113 0, NULL, numericStringValidate, NULL}, 6114 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", 6115 0, NULL, NULL, NULL}, 6116 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", 6117 0, NULL, numericoidValidate, NULL}, 6118 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", 6119 0, NULL, IA5StringValidate, NULL}, 6120 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", 6121 0, NULL, blobValidate, NULL}, 6122 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", 6123 0, NULL, postalAddressValidate, NULL}, 6124 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", 6125 0, NULL, NULL, NULL}, 6126 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", 6127 0, NULL, NULL, NULL}, 6128 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", 6129 0, NULL, printableStringValidate, NULL}, 6130 /* moved here because now depends on Directory String, IA5 String 6131 * and Printable String */ 6132 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 6133 0, country_gen_syn, countryStringValidate, NULL}, 6134 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )", 6135 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */ 6136 0, NULL, subtreeSpecificationValidate, NULL}, 6137 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " 6138 X_BINARY X_NOT_H_R ")", 6139 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 6140 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", 6141 0, NULL, printableStringValidate, NULL}, 6142 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", 6143 0, NULL, NULL, NULL}, 6144 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", 6145 0, NULL, printablesStringValidate, NULL}, 6146 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 6147 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", 6148 0, NULL, utcTimeValidate, NULL}, 6149 #endif 6150 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", 6151 0, NULL, NULL, NULL}, 6152 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )", 6153 0, NULL, NULL, NULL}, 6154 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )", 6155 0, NULL, NULL, NULL}, 6156 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )", 6157 0, NULL, NULL, NULL}, 6158 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", 6159 0, NULL, NULL, NULL}, 6160 6161 /* RFC 2307 NIS Syntaxes */ 6162 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )", 6163 0, NULL, nisNetgroupTripleValidate, NULL}, 6164 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", 6165 0, NULL, bootParameterValidate, NULL}, 6166 6167 /* draft-zeilenga-ldap-x509 */ 6168 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )", 6169 SLAP_SYNTAX_HIDE, NULL, 6170 serialNumberAndIssuerValidate, 6171 serialNumberAndIssuerPretty}, 6172 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )", 6173 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6174 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )", 6175 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6176 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )", 6177 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6178 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )", 6179 SLAP_SYNTAX_HIDE, NULL, 6180 issuerAndThisUpdateValidate, 6181 issuerAndThisUpdatePretty}, 6182 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )", 6183 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6184 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )", 6185 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6186 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )", 6187 SLAP_SYNTAX_HIDE, NULL, 6188 serialNumberAndIssuerSerialValidate, 6189 serialNumberAndIssuerSerialPretty}, 6190 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )", 6191 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6192 6193 #ifdef SLAPD_AUTHPASSWD 6194 /* needs updating */ 6195 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )", 6196 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6197 #endif 6198 6199 {"( 1.3.6.1.1.16.1 DESC 'UUID' )", 6200 0, NULL, UUIDValidate, UUIDPretty}, 6201 6202 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )", 6203 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty }, 6204 6205 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )", 6206 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty }, 6207 6208 /* OpenLDAP Void Syntax */ 6209 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , 6210 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL}, 6211 6212 /* FIXME: OID is unused, but not registered yet */ 6213 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )", 6214 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty}, 6215 6216 {NULL, 0, NULL, NULL, NULL} 6217 }; 6218 6219 char *csnSIDMatchSyntaxes[] = { 6220 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */, 6221 NULL 6222 }; 6223 char *certificateExactMatchSyntaxes[] = { 6224 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 6225 NULL 6226 }; 6227 char *certificateListExactMatchSyntaxes[] = { 6228 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */, 6229 NULL 6230 }; 6231 char *attributeCertificateExactMatchSyntaxes[] = { 6232 attributeCertificateSyntaxOID /* attributeCertificate */, 6233 NULL 6234 }; 6235 6236 #ifdef LDAP_COMP_MATCH 6237 char *componentFilterMatchSyntaxes[] = { 6238 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 6239 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */, 6240 attributeCertificateSyntaxOID /* attributeCertificate */, 6241 NULL 6242 }; 6243 #endif 6244 6245 char *directoryStringSyntaxes[] = { 6246 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */, 6247 NULL 6248 }; 6249 char *integerFirstComponentMatchSyntaxes[] = { 6250 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */, 6251 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */, 6252 NULL 6253 }; 6254 char *objectIdentifierFirstComponentMatchSyntaxes[] = { 6255 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */, 6256 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */, 6257 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */, 6258 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */, 6259 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */, 6260 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */, 6261 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */, 6262 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */, 6263 NULL 6264 }; 6265 6266 /* 6267 * Other matching rules in X.520 that we do not use (yet): 6268 * 6269 * 2.5.13.25 uTCTimeMatch 6270 * 2.5.13.26 uTCTimeOrderingMatch 6271 * 2.5.13.31* directoryStringFirstComponentMatch 6272 * 2.5.13.32* wordMatch 6273 * 2.5.13.33* keywordMatch 6274 * 2.5.13.36+ certificatePairExactMatch 6275 * 2.5.13.37+ certificatePairMatch 6276 * 2.5.13.40+ algorithmIdentifierMatch 6277 * 2.5.13.41* storedPrefixMatch 6278 * 2.5.13.42 attributeCertificateMatch 6279 * 2.5.13.43 readerAndKeyIDMatch 6280 * 2.5.13.44 attributeIntegrityMatch 6281 * 6282 * (*) described in RFC 3698 (LDAP: Additional Matching Rules) 6283 * (+) described in draft-zeilenga-ldap-x509 6284 */ 6285 static slap_mrule_defs_rec mrule_defs[] = { 6286 /* 6287 * EQUALITY matching rules must be listed after associated APPROX 6288 * matching rules. So, we list all APPROX matching rules first. 6289 */ 6290 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' " 6291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6292 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 6293 NULL, NULL, directoryStringApproxMatch, 6294 directoryStringApproxIndexer, directoryStringApproxFilter, 6295 NULL}, 6296 6297 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' " 6298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6299 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 6300 NULL, NULL, IA5StringApproxMatch, 6301 IA5StringApproxIndexer, IA5StringApproxFilter, 6302 NULL}, 6303 6304 /* 6305 * Other matching rules 6306 */ 6307 6308 {"( 2.5.13.0 NAME 'objectIdentifierMatch' " 6309 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 6310 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6311 NULL, NULL, octetStringMatch, 6312 octetStringIndexer, octetStringFilter, 6313 NULL }, 6314 6315 {"( 2.5.13.1 NAME 'distinguishedNameMatch' " 6316 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6317 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6318 NULL, dnNormalize, dnMatch, 6319 octetStringIndexer, octetStringFilter, 6320 NULL }, 6321 6322 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' " 6323 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6324 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6325 NULL, dnNormalize, dnRelativeMatch, 6326 NULL, NULL, 6327 NULL }, 6328 6329 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' " 6330 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6331 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6332 NULL, dnNormalize, dnRelativeMatch, 6333 NULL, NULL, 6334 NULL }, 6335 6336 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' " 6337 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6338 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6339 NULL, dnNormalize, dnRelativeMatch, 6340 NULL, NULL, 6341 NULL }, 6342 6343 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' " 6344 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6345 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6346 NULL, dnNormalize, dnRelativeMatch, 6347 NULL, NULL, 6348 NULL }, 6349 6350 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' " 6351 "SYNTAX 1.2.36.79672281.1.5.0 )", 6352 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6353 NULL, rdnNormalize, rdnMatch, 6354 octetStringIndexer, octetStringFilter, 6355 NULL }, 6356 6357 #ifdef LDAP_COMP_MATCH 6358 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' " 6359 "SYNTAX 1.2.36.79672281.1.5.2 )", 6360 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes, 6361 NULL, NULL , componentFilterMatch, 6362 octetStringIndexer, octetStringFilter, 6363 NULL }, 6364 6365 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' " 6366 "SYNTAX 1.2.36.79672281.1.5.3 )", 6367 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 6368 NULL, NULL , allComponentsMatch, 6369 octetStringIndexer, octetStringFilter, 6370 NULL }, 6371 6372 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' " 6373 "SYNTAX 1.2.36.79672281.1.5.3 )", 6374 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 6375 NULL, NULL , directoryComponentsMatch, 6376 octetStringIndexer, octetStringFilter, 6377 NULL }, 6378 #endif 6379 6380 {"( 2.5.13.2 NAME 'caseIgnoreMatch' " 6381 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6382 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 6383 NULL, UTF8StringNormalize, octetStringMatch, 6384 octetStringIndexer, octetStringFilter, 6385 directoryStringApproxMatchOID }, 6386 6387 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' " 6388 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6389 SLAP_MR_ORDERING, directoryStringSyntaxes, 6390 NULL, UTF8StringNormalize, octetStringOrderingMatch, 6391 NULL, NULL, 6392 "caseIgnoreMatch" }, 6393 6394 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " 6395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 6396 SLAP_MR_SUBSTR, directoryStringSyntaxes, 6397 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 6398 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6399 "caseIgnoreMatch" }, 6400 6401 {"( 2.5.13.5 NAME 'caseExactMatch' " 6402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6403 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 6404 NULL, UTF8StringNormalize, octetStringMatch, 6405 octetStringIndexer, octetStringFilter, 6406 directoryStringApproxMatchOID }, 6407 6408 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' " 6409 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6410 SLAP_MR_ORDERING, directoryStringSyntaxes, 6411 NULL, UTF8StringNormalize, octetStringOrderingMatch, 6412 NULL, NULL, 6413 "caseExactMatch" }, 6414 6415 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " 6416 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 6417 SLAP_MR_SUBSTR, directoryStringSyntaxes, 6418 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 6419 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6420 "caseExactMatch" }, 6421 6422 {"( 2.5.13.8 NAME 'numericStringMatch' " 6423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 6424 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6425 NULL, numericStringNormalize, octetStringMatch, 6426 octetStringIndexer, octetStringFilter, 6427 NULL }, 6428 6429 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' " 6430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 6431 SLAP_MR_ORDERING, NULL, 6432 NULL, numericStringNormalize, octetStringOrderingMatch, 6433 NULL, NULL, 6434 "numericStringMatch" }, 6435 6436 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' " 6437 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 6438 SLAP_MR_SUBSTR, NULL, 6439 NULL, numericStringNormalize, octetStringSubstringsMatch, 6440 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6441 "numericStringMatch" }, 6442 6443 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' " 6444 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", 6445 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6446 NULL, postalAddressNormalize, octetStringMatch, 6447 octetStringIndexer, octetStringFilter, 6448 NULL }, 6449 6450 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' " 6451 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 6452 SLAP_MR_SUBSTR, NULL, 6453 NULL, NULL, NULL, NULL, NULL, 6454 "caseIgnoreListMatch" }, 6455 6456 {"( 2.5.13.13 NAME 'booleanMatch' " 6457 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )", 6458 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6459 NULL, NULL, booleanMatch, 6460 octetStringIndexer, octetStringFilter, 6461 NULL }, 6462 6463 {"( 2.5.13.14 NAME 'integerMatch' " 6464 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6465 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6466 NULL, NULL, integerMatch, 6467 integerIndexer, integerFilter, 6468 NULL }, 6469 6470 {"( 2.5.13.15 NAME 'integerOrderingMatch' " 6471 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6472 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 6473 NULL, NULL, integerMatch, 6474 NULL, NULL, 6475 "integerMatch" }, 6476 6477 {"( 2.5.13.16 NAME 'bitStringMatch' " 6478 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", 6479 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6480 NULL, NULL, octetStringMatch, 6481 octetStringIndexer, octetStringFilter, 6482 NULL }, 6483 6484 {"( 2.5.13.17 NAME 'octetStringMatch' " 6485 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6486 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6487 NULL, NULL, octetStringMatch, 6488 octetStringIndexer, octetStringFilter, 6489 NULL }, 6490 6491 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' " 6492 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6493 SLAP_MR_ORDERING, NULL, 6494 NULL, NULL, octetStringOrderingMatch, 6495 NULL, NULL, 6496 "octetStringMatch" }, 6497 6498 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' " 6499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6500 SLAP_MR_SUBSTR, NULL, 6501 NULL, NULL, octetStringSubstringsMatch, 6502 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6503 "octetStringMatch" }, 6504 6505 {"( 2.5.13.20 NAME 'telephoneNumberMatch' " 6506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", 6507 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6508 NULL, 6509 telephoneNumberNormalize, octetStringMatch, 6510 octetStringIndexer, octetStringFilter, 6511 NULL }, 6512 6513 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' " 6514 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", 6515 SLAP_MR_SUBSTR, NULL, 6516 NULL, telephoneNumberNormalize, octetStringSubstringsMatch, 6517 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6518 "telephoneNumberMatch" }, 6519 6520 {"( 2.5.13.22 NAME 'presentationAddressMatch' " 6521 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", 6522 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6523 NULL, NULL, NULL, NULL, NULL, NULL }, 6524 6525 {"( 2.5.13.23 NAME 'uniqueMemberMatch' " 6526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", 6527 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6528 NULL, uniqueMemberNormalize, uniqueMemberMatch, 6529 uniqueMemberIndexer, uniqueMemberFilter, 6530 NULL }, 6531 6532 {"( 2.5.13.24 NAME 'protocolInformationMatch' " 6533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", 6534 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6535 NULL, NULL, NULL, NULL, NULL, NULL }, 6536 6537 {"( 2.5.13.27 NAME 'generalizedTimeMatch' " 6538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 6539 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6540 NULL, generalizedTimeNormalize, octetStringMatch, 6541 generalizedTimeIndexer, generalizedTimeFilter, 6542 NULL }, 6543 6544 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " 6545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 6546 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 6547 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch, 6548 NULL, NULL, 6549 "generalizedTimeMatch" }, 6550 6551 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' " 6552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6553 SLAP_MR_EQUALITY | SLAP_MR_EXT, 6554 integerFirstComponentMatchSyntaxes, 6555 NULL, firstComponentNormalize, integerMatch, 6556 octetStringIndexer, octetStringFilter, 6557 NULL }, 6558 6559 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' " 6560 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 6561 SLAP_MR_EQUALITY | SLAP_MR_EXT, 6562 objectIdentifierFirstComponentMatchSyntaxes, 6563 NULL, firstComponentNormalize, octetStringMatch, 6564 octetStringIndexer, octetStringFilter, 6565 NULL }, 6566 6567 {"( 2.5.13.34 NAME 'certificateExactMatch' " 6568 "SYNTAX 1.3.6.1.1.15.1 )", 6569 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, 6570 NULL, certificateExactNormalize, octetStringMatch, 6571 octetStringIndexer, octetStringFilter, 6572 NULL }, 6573 6574 {"( 2.5.13.35 NAME 'certificateMatch' " 6575 "SYNTAX 1.3.6.1.1.15.2 )", 6576 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6577 NULL, NULL, NULL, NULL, NULL, 6578 NULL }, 6579 6580 {"( 2.5.13.38 NAME 'certificateListExactMatch' " 6581 "SYNTAX 1.3.6.1.1.15.5 )", 6582 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes, 6583 NULL, certificateListExactNormalize, octetStringMatch, 6584 octetStringIndexer, octetStringFilter, 6585 NULL }, 6586 6587 {"( 2.5.13.39 NAME 'certificateListMatch' " 6588 "SYNTAX 1.3.6.1.1.15.6 )", 6589 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6590 NULL, NULL, NULL, NULL, NULL, 6591 NULL }, 6592 6593 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' " 6594 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )", 6595 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes, 6596 NULL, attributeCertificateExactNormalize, octetStringMatch, 6597 octetStringIndexer, octetStringFilter, 6598 NULL }, 6599 6600 {"( 2.5.13.46 NAME 'attributeCertificateMatch' " 6601 "SYNTAX " attributeCertificateAssertionSyntaxOID " )", 6602 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL, 6603 NULL, NULL, NULL, NULL, NULL, 6604 NULL }, 6605 6606 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " 6607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6608 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6609 NULL, IA5StringNormalize, octetStringMatch, 6610 octetStringIndexer, octetStringFilter, 6611 IA5StringApproxMatchOID }, 6612 6613 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' " 6614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6615 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6616 NULL, IA5StringNormalize, octetStringMatch, 6617 octetStringIndexer, octetStringFilter, 6618 IA5StringApproxMatchOID }, 6619 6620 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' " 6621 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6622 SLAP_MR_SUBSTR, NULL, 6623 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 6624 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6625 "caseIgnoreIA5Match" }, 6626 6627 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' " 6628 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6629 SLAP_MR_SUBSTR, NULL, 6630 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 6631 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6632 "caseExactIA5Match" }, 6633 6634 #ifdef SLAPD_AUTHPASSWD 6635 /* needs updating */ 6636 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' " 6637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6638 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 6639 NULL, NULL, authPasswordMatch, 6640 NULL, NULL, 6641 NULL}, 6642 #endif 6643 6644 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' " 6645 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6646 SLAP_MR_EXT, NULL, 6647 NULL, NULL, integerBitAndMatch, 6648 NULL, NULL, 6649 "integerMatch" }, 6650 6651 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' " 6652 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6653 SLAP_MR_EXT, NULL, 6654 NULL, NULL, integerBitOrMatch, 6655 NULL, NULL, 6656 "integerMatch" }, 6657 6658 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' " 6659 "SYNTAX 1.3.6.1.1.16.1 )", 6660 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL, 6661 NULL, UUIDNormalize, octetStringMatch, 6662 octetStringIndexer, octetStringFilter, 6663 NULL}, 6664 6665 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' " 6666 "SYNTAX 1.3.6.1.1.16.1 )", 6667 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL, 6668 NULL, UUIDNormalize, octetStringOrderingMatch, 6669 octetStringIndexer, octetStringFilter, 6670 "UUIDMatch"}, 6671 6672 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' " 6673 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 6674 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL, 6675 NULL, csnNormalize, csnMatch, 6676 csnIndexer, csnFilter, 6677 NULL}, 6678 6679 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' " 6680 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 6681 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, 6682 NULL, csnNormalize, csnOrderingMatch, 6683 NULL, NULL, 6684 "CSNMatch" }, 6685 6686 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' " 6687 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )", 6688 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes, 6689 NULL, csnSidNormalize, octetStringMatch, 6690 octetStringIndexer, octetStringFilter, 6691 NULL }, 6692 6693 /* FIXME: OID is unused, but not registered yet */ 6694 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' " 6695 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", 6696 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 6697 NULL, authzNormalize, authzMatch, 6698 NULL, NULL, 6699 NULL}, 6700 6701 {NULL, SLAP_MR_NONE, NULL, 6702 NULL, NULL, NULL, NULL, NULL, 6703 NULL } 6704 }; 6705 6706 int 6707 slap_schema_init( void ) 6708 { 6709 int res; 6710 int i; 6711 6712 /* we should only be called once (from main) */ 6713 assert( schema_init_done == 0 ); 6714 6715 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { 6716 res = register_syntax( &syntax_defs[i] ); 6717 6718 if ( res ) { 6719 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n", 6720 syntax_defs[i].sd_desc ); 6721 return LDAP_OTHER; 6722 } 6723 } 6724 6725 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) { 6726 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE && 6727 mrule_defs[i].mrd_compat_syntaxes == NULL ) 6728 { 6729 fprintf( stderr, 6730 "slap_schema_init: Ignoring unusable matching rule %s\n", 6731 mrule_defs[i].mrd_desc ); 6732 continue; 6733 } 6734 6735 res = register_matching_rule( &mrule_defs[i] ); 6736 6737 if ( res ) { 6738 fprintf( stderr, 6739 "slap_schema_init: Error registering matching rule %s\n", 6740 mrule_defs[i].mrd_desc ); 6741 return LDAP_OTHER; 6742 } 6743 } 6744 6745 res = slap_schema_load(); 6746 schema_init_done = 1; 6747 return res; 6748 } 6749 6750 void 6751 schema_destroy( void ) 6752 { 6753 oidm_destroy(); 6754 oc_destroy(); 6755 at_destroy(); 6756 mr_destroy(); 6757 mru_destroy(); 6758 syn_destroy(); 6759 6760 if( schema_init_done ) { 6761 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex ); 6762 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex ); 6763 } 6764 } 6765