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