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