1 /* $NetBSD: schema_init.c,v 1.2 2020/08/11 13:15:39 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-2020 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.2 2020/08/11 13:15:39 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, unless the result would be empty */ 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 *q; 2244 ber_len_t c; 2245 2246 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 2247 2248 /* Ensure q is big enough, though validator should have caught this */ 2249 if ( BER_BVISEMPTY( val )) { 2250 BER_BVZERO( normalized ); 2251 return LDAP_INVALID_SYNTAX; 2252 } 2253 2254 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 2255 2256 for( c = 0; c < val->bv_len; c++ ) { 2257 if ( ! ( ASCII_SPACE( val->bv_val[c] ) || val->bv_val[c] == '-' )) { 2258 *q++ = val->bv_val[c]; 2259 } 2260 } 2261 if ( q == normalized->bv_val ) { 2262 *q++ = ' '; 2263 } 2264 *q = '\0'; 2265 2266 normalized->bv_len = q - normalized->bv_val; 2267 2268 return LDAP_SUCCESS; 2269 } 2270 2271 static int 2272 postalAddressValidate( 2273 Syntax *syntax, 2274 struct berval *in ) 2275 { 2276 struct berval bv = *in; 2277 ber_len_t c; 2278 2279 for ( c = 0; c < in->bv_len; c++ ) { 2280 if ( in->bv_val[c] == '\\' ) { 2281 c++; 2282 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0 2283 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 ) 2284 { 2285 return LDAP_INVALID_SYNTAX; 2286 } 2287 continue; 2288 } 2289 2290 if ( in->bv_val[c] == '$' ) { 2291 bv.bv_len = &in->bv_val[c] - bv.bv_val; 2292 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) { 2293 return LDAP_INVALID_SYNTAX; 2294 } 2295 bv.bv_val = &in->bv_val[c] + 1; 2296 } 2297 } 2298 2299 bv.bv_len = &in->bv_val[c] - bv.bv_val; 2300 return UTF8StringValidate( NULL, &bv ); 2301 } 2302 2303 static int 2304 postalAddressNormalize( 2305 slap_mask_t usage, 2306 Syntax *syntax, 2307 MatchingRule *mr, 2308 struct berval *val, 2309 struct berval *normalized, 2310 void *ctx ) 2311 { 2312 BerVarray lines = NULL, nlines = NULL; 2313 ber_len_t l, c; 2314 int rc = LDAP_SUCCESS; 2315 MatchingRule *xmr = NULL; 2316 char *p; 2317 2318 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) { 2319 xmr = slap_schema.si_mr_caseIgnoreMatch; 2320 2321 } else { 2322 xmr = slap_schema.si_mr_caseExactMatch; 2323 } 2324 2325 for ( l = 0, c = 0; c < val->bv_len; c++ ) { 2326 if ( val->bv_val[c] == '$' ) { 2327 l++; 2328 } 2329 } 2330 2331 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx ); 2332 nlines = &lines[l + 2]; 2333 2334 lines[0].bv_val = val->bv_val; 2335 for ( l = 0, c = 0; c < val->bv_len; c++ ) { 2336 if ( val->bv_val[c] == '$' ) { 2337 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val; 2338 l++; 2339 lines[l].bv_val = &val->bv_val[c + 1]; 2340 } 2341 } 2342 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val; 2343 2344 normalized->bv_len = c = l; 2345 2346 for ( l = 0; l <= c; l++ ) { 2347 /* NOTE: we directly normalize each line, 2348 * without unescaping the values, since the special 2349 * values '\24' ('$') and '\5C' ('\') are not affected 2350 * by normalization */ 2351 if ( !lines[l].bv_len ) { 2352 nlines[l].bv_len = 0; 2353 nlines[l].bv_val = NULL; 2354 continue; 2355 } 2356 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx ); 2357 if ( rc != LDAP_SUCCESS ) { 2358 rc = LDAP_INVALID_SYNTAX; 2359 goto done; 2360 } 2361 2362 normalized->bv_len += nlines[l].bv_len; 2363 } 2364 2365 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2366 2367 p = normalized->bv_val; 2368 for ( l = 0; l <= c ; l++ ) { 2369 p = lutil_strbvcopy( p, &nlines[l] ); 2370 *p++ = '$'; 2371 } 2372 *--p = '\0'; 2373 2374 assert( p == &normalized->bv_val[normalized->bv_len] ); 2375 2376 done:; 2377 if ( nlines != NULL ) { 2378 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) { 2379 slap_sl_free( nlines[l].bv_val, ctx ); 2380 } 2381 2382 slap_sl_free( lines, ctx ); 2383 } 2384 2385 return rc; 2386 } 2387 2388 int 2389 numericoidValidate( 2390 Syntax *syntax, 2391 struct berval *in ) 2392 { 2393 struct berval val = *in; 2394 2395 if( BER_BVISEMPTY( &val ) ) { 2396 /* disallow empty strings */ 2397 return LDAP_INVALID_SYNTAX; 2398 } 2399 2400 while( OID_LEADCHAR( val.bv_val[0] ) ) { 2401 if ( val.bv_len == 1 ) { 2402 return LDAP_SUCCESS; 2403 } 2404 2405 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) { 2406 break; 2407 } 2408 2409 val.bv_val++; 2410 val.bv_len--; 2411 2412 while ( OID_LEADCHAR( val.bv_val[0] )) { 2413 val.bv_val++; 2414 val.bv_len--; 2415 2416 if ( val.bv_len == 0 ) { 2417 return LDAP_SUCCESS; 2418 } 2419 } 2420 2421 if( !OID_SEPARATOR( val.bv_val[0] )) { 2422 break; 2423 } 2424 2425 val.bv_val++; 2426 val.bv_len--; 2427 } 2428 2429 return LDAP_INVALID_SYNTAX; 2430 } 2431 2432 static int 2433 integerValidate( 2434 Syntax *syntax, 2435 struct berval *in ) 2436 { 2437 ber_len_t i; 2438 struct berval val = *in; 2439 2440 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX; 2441 2442 if ( val.bv_val[0] == '-' ) { 2443 val.bv_len--; 2444 val.bv_val++; 2445 2446 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */ 2447 return LDAP_INVALID_SYNTAX; 2448 } 2449 2450 if( val.bv_val[0] == '0' ) { /* "-0" */ 2451 return LDAP_INVALID_SYNTAX; 2452 } 2453 2454 } else if ( val.bv_val[0] == '0' ) { 2455 if( val.bv_len > 1 ) { /* "0<more>" */ 2456 return LDAP_INVALID_SYNTAX; 2457 } 2458 2459 return LDAP_SUCCESS; 2460 } 2461 2462 for( i=0; i < val.bv_len; i++ ) { 2463 if( !ASCII_DIGIT(val.bv_val[i]) ) { 2464 return LDAP_INVALID_SYNTAX; 2465 } 2466 } 2467 2468 return LDAP_SUCCESS; 2469 } 2470 2471 static int 2472 integerMatch( 2473 int *matchp, 2474 slap_mask_t flags, 2475 Syntax *syntax, 2476 MatchingRule *mr, 2477 struct berval *value, 2478 void *assertedValue ) 2479 { 2480 struct berval *asserted = (struct berval *) assertedValue; 2481 int vsign = 1, asign = 1; /* default sign = '+' */ 2482 struct berval v, a; 2483 int match; 2484 2485 v = *value; 2486 if( v.bv_val[0] == '-' ) { 2487 vsign = -1; 2488 v.bv_val++; 2489 v.bv_len--; 2490 } 2491 2492 if( BER_BVISEMPTY( &v ) ) vsign = 0; 2493 2494 a = *asserted; 2495 if( a.bv_val[0] == '-' ) { 2496 asign = -1; 2497 a.bv_val++; 2498 a.bv_len--; 2499 } 2500 2501 if( BER_BVISEMPTY( &a ) ) vsign = 0; 2502 2503 match = vsign - asign; 2504 if( match == 0 ) { 2505 match = ( v.bv_len != a.bv_len 2506 ? ( v.bv_len < a.bv_len ? -1 : 1 ) 2507 : memcmp( v.bv_val, a.bv_val, v.bv_len )); 2508 if( vsign < 0 ) match = -match; 2509 } 2510 2511 /* Ordering rule used in extensible match filter? */ 2512 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) ) 2513 match = (match >= 0); 2514 2515 *matchp = match; 2516 return LDAP_SUCCESS; 2517 } 2518 2519 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */ 2520 #define INDEX_INTLEN_CHOP 7 2521 #define INDEX_INTLEN_CHOPBYTES 3 2522 2523 static int 2524 integerVal2Key( 2525 struct berval *in, 2526 struct berval *key, 2527 struct berval *tmp, 2528 void *ctx ) 2529 { 2530 /* Integer index key format, designed for memcmp to collate correctly: 2531 * if too large: one's complement sign*<approx exponent=chopped bytes>, 2532 * two's complement value (sign-extended or chopped as needed), 2533 * however in first byte above, the top <number of exponent-bytes + 1> 2534 * bits are the inverse sign and next bit is the sign as delimiter. 2535 */ 2536 ber_slen_t k = index_intlen_strlen; 2537 ber_len_t chop = 0; 2538 unsigned signmask = ~0x7fU; 2539 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff; 2540 struct berval val = *in, itmp = *tmp; 2541 2542 if ( val.bv_val[0] != '-' ) { 2543 neg = 0; 2544 --k; 2545 } 2546 2547 /* Chop least significant digits, increase length instead */ 2548 if ( val.bv_len > (ber_len_t) k ) { 2549 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */ 2550 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */ 2551 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */ 2552 } 2553 2554 if ( lutil_str2bin( &val, &itmp, ctx )) { 2555 return LDAP_INVALID_SYNTAX; 2556 } 2557 2558 /* Omit leading sign byte */ 2559 if ( itmp.bv_val[0] == neg ) { 2560 itmp.bv_val++; 2561 itmp.bv_len--; 2562 } 2563 2564 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop); 2565 if ( k > 0 ) { 2566 assert( chop == 0 ); 2567 memset( key->bv_val, neg, k ); /* sign-extend */ 2568 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) { 2569 /* Got exponent -k, or no room for 2 sign bits */ 2570 lenp = lenbuf + sizeof(lenbuf); 2571 chop = - (ber_len_t) k; 2572 do { 2573 *--lenp = ((unsigned char) chop & 0xff) ^ neg; 2574 signmask >>= 1; 2575 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) ); 2576 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff) 2577 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */ 2578 k = (lenbuf + sizeof(lenbuf)) - lenp; 2579 if ( k > (ber_slen_t) index_intlen ) 2580 k = index_intlen; 2581 memcpy( key->bv_val, lenp, k ); 2582 itmp.bv_len = index_intlen - k; 2583 } 2584 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len ); 2585 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */ 2586 return 0; 2587 } 2588 2589 /* Index generation function: Ordered index */ 2590 static int 2591 integerIndexer( 2592 slap_mask_t use, 2593 slap_mask_t flags, 2594 Syntax *syntax, 2595 MatchingRule *mr, 2596 struct berval *prefix, 2597 BerVarray values, 2598 BerVarray *keysp, 2599 void *ctx ) 2600 { 2601 char ibuf[64]; 2602 struct berval itmp; 2603 BerVarray keys; 2604 ber_len_t vlen; 2605 int i, rc; 2606 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2607 2608 /* count the values and find max needed length */ 2609 vlen = 0; 2610 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2611 if ( vlen < values[i].bv_len ) 2612 vlen = values[i].bv_len; 2613 } 2614 if ( vlen > maxstrlen ) 2615 vlen = maxstrlen; 2616 2617 /* we should have at least one value at this point */ 2618 assert( i > 0 ); 2619 2620 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 2621 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { 2622 keys[i].bv_len = index_intlen; 2623 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx ); 2624 } 2625 keys[i].bv_len = 0; 2626 keys[i].bv_val = NULL; 2627 2628 if ( vlen > sizeof(ibuf) ) { 2629 itmp.bv_val = slap_sl_malloc( vlen, ctx ); 2630 } else { 2631 itmp.bv_val = ibuf; 2632 } 2633 itmp.bv_len = sizeof(ibuf); 2634 2635 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) { 2636 if ( itmp.bv_val != ibuf ) { 2637 itmp.bv_len = values[i].bv_len; 2638 if ( itmp.bv_len <= sizeof(ibuf) ) 2639 itmp.bv_len = sizeof(ibuf); 2640 else if ( itmp.bv_len > maxstrlen ) 2641 itmp.bv_len = maxstrlen; 2642 } 2643 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx ); 2644 if ( rc ) { 2645 slap_sl_free( keys, ctx ); 2646 goto func_leave; 2647 } 2648 } 2649 *keysp = keys; 2650 func_leave: 2651 if ( itmp.bv_val != ibuf ) { 2652 slap_sl_free( itmp.bv_val, ctx ); 2653 } 2654 return rc; 2655 } 2656 2657 /* Index generation function: Ordered index */ 2658 static int 2659 integerFilter( 2660 slap_mask_t use, 2661 slap_mask_t flags, 2662 Syntax *syntax, 2663 MatchingRule *mr, 2664 struct berval *prefix, 2665 void * assertedValue, 2666 BerVarray *keysp, 2667 void *ctx ) 2668 { 2669 char ibuf[64]; 2670 struct berval iv; 2671 BerVarray keys; 2672 struct berval *value; 2673 int rc; 2674 2675 value = (struct berval *) assertedValue; 2676 2677 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 2678 2679 keys[0].bv_len = index_intlen; 2680 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx ); 2681 keys[1].bv_len = 0; 2682 keys[1].bv_val = NULL; 2683 2684 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1 2685 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1; 2686 if ( iv.bv_len > (int) sizeof(ibuf) ) { 2687 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx ); 2688 } else { 2689 iv.bv_val = ibuf; 2690 iv.bv_len = sizeof(ibuf); 2691 } 2692 2693 rc = integerVal2Key( value, keys, &iv, ctx ); 2694 2695 if ( iv.bv_val != ibuf ) { 2696 slap_sl_free( iv.bv_val, ctx ); 2697 } 2698 2699 if ( rc == 0 ) 2700 *keysp = keys; 2701 else 2702 slap_sl_free( keys, ctx ); 2703 2704 return rc; 2705 } 2706 2707 static int 2708 countryStringValidate( 2709 Syntax *syntax, 2710 struct berval *val ) 2711 { 2712 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX; 2713 2714 if( !SLAP_PRINTABLE(val->bv_val[0]) ) { 2715 return LDAP_INVALID_SYNTAX; 2716 } 2717 if( !SLAP_PRINTABLE(val->bv_val[1]) ) { 2718 return LDAP_INVALID_SYNTAX; 2719 } 2720 2721 return LDAP_SUCCESS; 2722 } 2723 2724 static int 2725 printableStringValidate( 2726 Syntax *syntax, 2727 struct berval *val ) 2728 { 2729 ber_len_t i; 2730 2731 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2732 2733 for(i=0; i < val->bv_len; i++) { 2734 if( !SLAP_PRINTABLE(val->bv_val[i]) ) { 2735 return LDAP_INVALID_SYNTAX; 2736 } 2737 } 2738 2739 return LDAP_SUCCESS; 2740 } 2741 2742 static int 2743 printablesStringValidate( 2744 Syntax *syntax, 2745 struct berval *val ) 2746 { 2747 ber_len_t i, len; 2748 2749 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; 2750 2751 for(i=0,len=0; i < val->bv_len; i++) { 2752 int c = val->bv_val[i]; 2753 2754 if( c == '$' ) { 2755 if( len == 0 ) { 2756 return LDAP_INVALID_SYNTAX; 2757 } 2758 len = 0; 2759 2760 } else if ( SLAP_PRINTABLE(c) ) { 2761 len++; 2762 } else { 2763 return LDAP_INVALID_SYNTAX; 2764 } 2765 } 2766 2767 if( len == 0 ) { 2768 return LDAP_INVALID_SYNTAX; 2769 } 2770 2771 return LDAP_SUCCESS; 2772 } 2773 2774 static int 2775 IA5StringValidate( 2776 Syntax *syntax, 2777 struct berval *val ) 2778 { 2779 ber_len_t i; 2780 2781 for(i=0; i < val->bv_len; i++) { 2782 if( !LDAP_ASCII(val->bv_val[i]) ) { 2783 return LDAP_INVALID_SYNTAX; 2784 } 2785 } 2786 2787 return LDAP_SUCCESS; 2788 } 2789 2790 static int 2791 IA5StringNormalize( 2792 slap_mask_t use, 2793 Syntax *syntax, 2794 MatchingRule *mr, 2795 struct berval *val, 2796 struct berval *normalized, 2797 void *ctx ) 2798 { 2799 char *p, *q, *end; 2800 int casefold = !SLAP_MR_ASSOCIATED( mr, 2801 slap_schema.si_mr_caseExactIA5Match ); 2802 2803 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); 2804 2805 p = val->bv_val; 2806 end = val->bv_val + val->bv_len; 2807 2808 /* Ignore initial whitespace */ 2809 while ( p < end && ASCII_SPACE( *p ) ) p++; 2810 2811 normalized->bv_len = p < end ? (val->bv_len - ( p - val->bv_val )) : 0; 2812 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2813 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len ); 2814 normalized->bv_val[normalized->bv_len] = '\0'; 2815 2816 p = q = normalized->bv_val; 2817 2818 while ( *p ) { 2819 if ( ASCII_SPACE( *p ) ) { 2820 *q++ = *p++; 2821 2822 /* Ignore the extra whitespace */ 2823 while ( ASCII_SPACE( *p ) ) { 2824 p++; 2825 } 2826 2827 } else if ( casefold ) { 2828 /* Most IA5 rules require casefolding */ 2829 *q++ = TOLOWER(*p); p++; 2830 2831 } else { 2832 *q++ = *p++; 2833 } 2834 } 2835 2836 assert( normalized->bv_val <= p ); 2837 assert( q <= p ); 2838 2839 /* 2840 * If the string ended in space, backup the pointer one 2841 * position. One is enough because the above loop collapsed 2842 * all whitespace to a single space. 2843 */ 2844 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q; 2845 2846 /* null terminate */ 2847 *q = '\0'; 2848 2849 normalized->bv_len = q - normalized->bv_val; 2850 2851 return LDAP_SUCCESS; 2852 } 2853 2854 static int 2855 UUIDValidate( 2856 Syntax *syntax, 2857 struct berval *in ) 2858 { 2859 int i; 2860 if( in->bv_len != 36 ) { 2861 return LDAP_INVALID_SYNTAX; 2862 } 2863 2864 for( i=0; i<36; i++ ) { 2865 switch(i) { 2866 case 8: 2867 case 13: 2868 case 18: 2869 case 23: 2870 if( in->bv_val[i] != '-' ) { 2871 return LDAP_INVALID_SYNTAX; 2872 } 2873 break; 2874 default: 2875 if( !ASCII_HEX( in->bv_val[i]) ) { 2876 return LDAP_INVALID_SYNTAX; 2877 } 2878 } 2879 } 2880 2881 return LDAP_SUCCESS; 2882 } 2883 2884 static int 2885 UUIDPretty( 2886 Syntax *syntax, 2887 struct berval *in, 2888 struct berval *out, 2889 void *ctx ) 2890 { 2891 int i; 2892 int rc=LDAP_INVALID_SYNTAX; 2893 2894 assert( in != NULL ); 2895 assert( out != NULL ); 2896 2897 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX; 2898 2899 out->bv_len = 36; 2900 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 2901 2902 for( i=0; i<36; i++ ) { 2903 switch(i) { 2904 case 8: 2905 case 13: 2906 case 18: 2907 case 23: 2908 if( in->bv_val[i] != '-' ) { 2909 goto handle_error; 2910 } 2911 out->bv_val[i] = '-'; 2912 break; 2913 2914 default: 2915 if( !ASCII_HEX( in->bv_val[i]) ) { 2916 goto handle_error; 2917 } 2918 out->bv_val[i] = TOLOWER( in->bv_val[i] ); 2919 } 2920 } 2921 2922 rc = LDAP_SUCCESS; 2923 out->bv_val[ out->bv_len ] = '\0'; 2924 2925 if( 0 ) { 2926 handle_error: 2927 slap_sl_free( out->bv_val, ctx ); 2928 out->bv_val = NULL; 2929 } 2930 2931 return rc; 2932 } 2933 2934 int 2935 UUIDNormalize( 2936 slap_mask_t usage, 2937 Syntax *syntax, 2938 MatchingRule *mr, 2939 struct berval *val, 2940 struct berval *normalized, 2941 void *ctx ) 2942 { 2943 unsigned char octet = '\0'; 2944 int i; 2945 int j; 2946 2947 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) { 2948 /* NOTE: must be a normalized UUID */ 2949 assert( val->bv_len == 16 ); 2950 2951 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx ); 2952 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val, 2953 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE ); 2954 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) ); 2955 2956 return LDAP_SUCCESS; 2957 } 2958 2959 normalized->bv_len = 16; 2960 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx ); 2961 2962 for( i=0, j=0; i<36; i++ ) { 2963 unsigned char nibble; 2964 if( val->bv_val[i] == '-' ) { 2965 continue; 2966 2967 } else if( ASCII_DIGIT( val->bv_val[i] ) ) { 2968 nibble = val->bv_val[i] - '0'; 2969 2970 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) { 2971 nibble = val->bv_val[i] - ('a'-10); 2972 2973 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) { 2974 nibble = val->bv_val[i] - ('A'-10); 2975 2976 } else { 2977 slap_sl_free( normalized->bv_val, ctx ); 2978 BER_BVZERO( normalized ); 2979 return LDAP_INVALID_SYNTAX; 2980 } 2981 2982 if( j & 1 ) { 2983 octet |= nibble; 2984 normalized->bv_val[j>>1] = octet; 2985 } else { 2986 octet = nibble << 4; 2987 } 2988 j++; 2989 } 2990 2991 normalized->bv_val[normalized->bv_len] = 0; 2992 return LDAP_SUCCESS; 2993 } 2994 2995 2996 2997 int 2998 numericStringValidate( 2999 Syntax *syntax, 3000 struct berval *in ) 3001 { 3002 ber_len_t i; 3003 3004 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX; 3005 3006 for(i=0; i < in->bv_len; i++) { 3007 if( !SLAP_NUMERIC(in->bv_val[i]) ) { 3008 return LDAP_INVALID_SYNTAX; 3009 } 3010 } 3011 3012 return LDAP_SUCCESS; 3013 } 3014 3015 static int 3016 numericStringNormalize( 3017 slap_mask_t usage, 3018 Syntax *syntax, 3019 MatchingRule *mr, 3020 struct berval *val, 3021 struct berval *normalized, 3022 void *ctx ) 3023 { 3024 /* removal all spaces */ 3025 char *p, *q; 3026 3027 assert( !BER_BVISEMPTY( val ) ); 3028 3029 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); 3030 3031 p = val->bv_val; 3032 q = normalized->bv_val; 3033 3034 while ( *p ) { 3035 if ( ASCII_SPACE( *p ) ) { 3036 /* Ignore whitespace */ 3037 p++; 3038 } else { 3039 *q++ = *p++; 3040 } 3041 } 3042 3043 /* we should have copied no more than is in val */ 3044 assert( (q - normalized->bv_val) <= (p - val->bv_val) ); 3045 3046 /* null terminate */ 3047 *q = '\0'; 3048 3049 normalized->bv_len = q - normalized->bv_val; 3050 3051 if( BER_BVISEMPTY( normalized ) ) { 3052 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx ); 3053 normalized->bv_val[0] = ' '; 3054 normalized->bv_val[1] = '\0'; 3055 normalized->bv_len = 1; 3056 } 3057 3058 return LDAP_SUCCESS; 3059 } 3060 3061 /* 3062 * Integer conversion macros that will use the largest available 3063 * type. 3064 */ 3065 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) 3066 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) 3067 # define SLAP_LONG long long 3068 #else 3069 # define SLAP_STRTOL(n,e,b) strtol(n,e,b) 3070 # define SLAP_LONG long 3071 #endif /* HAVE_STRTOLL ... */ 3072 3073 static int 3074 integerBitAndMatch( 3075 int *matchp, 3076 slap_mask_t flags, 3077 Syntax *syntax, 3078 MatchingRule *mr, 3079 struct berval *value, 3080 void *assertedValue ) 3081 { 3082 SLAP_LONG lValue, lAssertedValue; 3083 3084 errno = 0; 3085 /* safe to assume integers are NUL terminated? */ 3086 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 3087 if( errno == ERANGE ) 3088 { 3089 return LDAP_CONSTRAINT_VIOLATION; 3090 } 3091 3092 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, 3093 NULL, 10); 3094 if( errno == ERANGE ) 3095 { 3096 return LDAP_CONSTRAINT_VIOLATION; 3097 } 3098 3099 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1; 3100 return LDAP_SUCCESS; 3101 } 3102 3103 static int 3104 integerBitOrMatch( 3105 int *matchp, 3106 slap_mask_t flags, 3107 Syntax *syntax, 3108 MatchingRule *mr, 3109 struct berval *value, 3110 void *assertedValue ) 3111 { 3112 SLAP_LONG lValue, lAssertedValue; 3113 3114 errno = 0; 3115 /* safe to assume integers are NUL terminated? */ 3116 lValue = SLAP_STRTOL(value->bv_val, NULL, 10); 3117 if( errno == ERANGE ) 3118 { 3119 return LDAP_CONSTRAINT_VIOLATION; 3120 } 3121 3122 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, 3123 NULL, 10); 3124 if( errno == ERANGE ) 3125 { 3126 return LDAP_CONSTRAINT_VIOLATION; 3127 } 3128 3129 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1; 3130 return LDAP_SUCCESS; 3131 } 3132 3133 static int 3134 checkNum( struct berval *in, struct berval *out ) 3135 { 3136 /* parse serialNumber */ 3137 ber_len_t neg = 0, extra = 0; 3138 char first = '\0'; 3139 3140 out->bv_val = in->bv_val; 3141 out->bv_len = 0; 3142 3143 if ( out->bv_val[0] == '-' ) { 3144 neg++; 3145 out->bv_len++; 3146 } 3147 3148 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) { 3149 first = out->bv_val[2]; 3150 extra = 2; 3151 3152 out->bv_len += STRLENOF("0x"); 3153 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3154 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break; 3155 } 3156 3157 } else if ( out->bv_val[0] == '\'' ) { 3158 first = out->bv_val[1]; 3159 extra = 3; 3160 3161 out->bv_len += STRLENOF("'"); 3162 3163 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3164 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break; 3165 } 3166 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) { 3167 return -1; 3168 } 3169 out->bv_len += STRLENOF("'H"); 3170 3171 } else { 3172 first = out->bv_val[0]; 3173 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) { 3174 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break; 3175 } 3176 } 3177 3178 if ( !( out->bv_len > neg ) ) { 3179 return -1; 3180 } 3181 3182 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) { 3183 return -1; 3184 } 3185 3186 return 0; 3187 } 3188 3189 static int 3190 serialNumberAndIssuerCheck( 3191 struct berval *in, 3192 struct berval *sn, 3193 struct berval *is, 3194 void *ctx ) 3195 { 3196 ber_len_t n; 3197 3198 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 3199 3200 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 3201 /* Parse old format */ 3202 is->bv_val = ber_bvchr( in, '$' ); 3203 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX; 3204 3205 sn->bv_val = in->bv_val; 3206 sn->bv_len = is->bv_val - in->bv_val; 3207 3208 is->bv_val++; 3209 is->bv_len = in->bv_len - (sn->bv_len + 1); 3210 3211 /* eat leading zeros */ 3212 for( n=0; n < (sn->bv_len-1); n++ ) { 3213 if( sn->bv_val[n] != '0' ) break; 3214 } 3215 sn->bv_val += n; 3216 sn->bv_len -= n; 3217 3218 for( n=0; n < sn->bv_len; n++ ) { 3219 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX; 3220 } 3221 3222 } else { 3223 /* Parse GSER format */ 3224 enum { 3225 HAVE_NONE = 0x0, 3226 HAVE_ISSUER = 0x1, 3227 HAVE_SN = 0x2, 3228 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN ) 3229 } have = HAVE_NONE; 3230 3231 int numdquotes = 0; 3232 struct berval x = *in; 3233 struct berval ni; 3234 x.bv_val++; 3235 x.bv_len -= 2; 3236 3237 do { 3238 /* eat leading spaces */ 3239 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3240 /* empty */; 3241 } 3242 3243 /* should be at issuer or serialNumber NamedValue */ 3244 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 3245 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX; 3246 3247 /* parse issuer */ 3248 x.bv_val += STRLENOF("issuer"); 3249 x.bv_len -= STRLENOF("issuer"); 3250 3251 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3252 x.bv_val++; 3253 x.bv_len--; 3254 3255 /* eat leading spaces */ 3256 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3257 /* empty */; 3258 } 3259 3260 /* For backward compatibility, this part is optional */ 3261 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) { 3262 x.bv_val += STRLENOF("rdnSequence:"); 3263 x.bv_len -= STRLENOF("rdnSequence:"); 3264 } 3265 3266 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3267 x.bv_val++; 3268 x.bv_len--; 3269 3270 is->bv_val = x.bv_val; 3271 is->bv_len = 0; 3272 3273 for ( ; is->bv_len < x.bv_len; ) { 3274 if ( is->bv_val[is->bv_len] != '"' ) { 3275 is->bv_len++; 3276 continue; 3277 } 3278 if ( is->bv_val[is->bv_len+1] == '"' ) { 3279 /* double dquote */ 3280 numdquotes++; 3281 is->bv_len += 2; 3282 continue; 3283 } 3284 break; 3285 } 3286 x.bv_val += is->bv_len + 1; 3287 x.bv_len -= is->bv_len + 1; 3288 3289 have |= HAVE_ISSUER; 3290 3291 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) 3292 { 3293 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX; 3294 3295 /* parse serialNumber */ 3296 x.bv_val += STRLENOF("serialNumber"); 3297 x.bv_len -= STRLENOF("serialNumber"); 3298 3299 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3300 x.bv_val++; 3301 x.bv_len--; 3302 3303 /* eat leading spaces */ 3304 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3305 /* empty */; 3306 } 3307 3308 if ( checkNum( &x, sn ) ) { 3309 return LDAP_INVALID_SYNTAX; 3310 } 3311 3312 x.bv_val += sn->bv_len; 3313 x.bv_len -= sn->bv_len; 3314 3315 have |= HAVE_SN; 3316 3317 } else { 3318 return LDAP_INVALID_SYNTAX; 3319 } 3320 3321 /* eat leading spaces */ 3322 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3323 /* empty */; 3324 } 3325 3326 if ( have == HAVE_ALL ) { 3327 break; 3328 } 3329 3330 if ( x.bv_val[0] != ',' ) { 3331 return LDAP_INVALID_SYNTAX; 3332 } 3333 3334 x.bv_val++; 3335 x.bv_len--; 3336 } while ( 1 ); 3337 3338 /* should have no characters left... */ 3339 if ( x.bv_len ) return LDAP_INVALID_SYNTAX; 3340 3341 if ( numdquotes == 0 ) { 3342 ber_dupbv_x( &ni, is, ctx ); 3343 3344 } else { 3345 ber_len_t src, dst; 3346 3347 ni.bv_len = is->bv_len - numdquotes; 3348 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 3349 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 3350 if ( is->bv_val[src] == '"' ) { 3351 src++; 3352 } 3353 ni.bv_val[dst] = is->bv_val[src]; 3354 } 3355 ni.bv_val[dst] = '\0'; 3356 } 3357 3358 *is = ni; 3359 } 3360 3361 return 0; 3362 } 3363 3364 static int 3365 serialNumberAndIssuerValidate( 3366 Syntax *syntax, 3367 struct berval *in ) 3368 { 3369 int rc; 3370 struct berval sn, i; 3371 3372 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n", 3373 in->bv_val, 0, 0 ); 3374 3375 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL ); 3376 if ( rc ) { 3377 goto done; 3378 } 3379 3380 /* validate DN -- doesn't handle double dquote */ 3381 rc = dnValidate( NULL, &i ); 3382 if ( rc ) { 3383 rc = LDAP_INVALID_SYNTAX; 3384 } 3385 3386 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3387 slap_sl_free( i.bv_val, NULL ); 3388 } 3389 3390 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n", 3391 in->bv_val, rc, 0 ); 3392 3393 done:; 3394 return rc; 3395 } 3396 3397 static int 3398 serialNumberAndIssuerPretty( 3399 Syntax *syntax, 3400 struct berval *in, 3401 struct berval *out, 3402 void *ctx ) 3403 { 3404 int rc; 3405 struct berval sn, i, ni = BER_BVNULL; 3406 char *p; 3407 3408 assert( in != NULL ); 3409 assert( out != NULL ); 3410 3411 BER_BVZERO( out ); 3412 3413 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", 3414 in->bv_val, 0, 0 ); 3415 3416 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3417 if ( rc ) { 3418 goto done; 3419 } 3420 3421 rc = dnPretty( syntax, &i, &ni, ctx ); 3422 3423 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3424 slap_sl_free( i.bv_val, ctx ); 3425 } 3426 3427 if ( rc ) { 3428 rc = LDAP_INVALID_SYNTAX; 3429 goto done; 3430 } 3431 3432 /* make room from sn + "$" */ 3433 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }") 3434 + sn.bv_len + ni.bv_len; 3435 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3436 3437 if ( out->bv_val == NULL ) { 3438 out->bv_len = 0; 3439 rc = LDAP_OTHER; 3440 goto done; 3441 } 3442 3443 p = out->bv_val; 3444 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3445 p = lutil_strbvcopy( p, &sn ); 3446 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3447 p = lutil_strbvcopy( p, &ni ); 3448 p = lutil_strcopy( p, /*{*/ "\" }" ); 3449 3450 assert( p == &out->bv_val[out->bv_len] ); 3451 3452 done:; 3453 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n", 3454 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 3455 3456 slap_sl_free( ni.bv_val, ctx ); 3457 3458 return LDAP_SUCCESS; 3459 } 3460 3461 static int 3462 slap_bin2hex( 3463 struct berval *in, 3464 struct berval *out, 3465 void *ctx ) 3466 3467 { 3468 /* Use hex format. '123456789abcdef'H */ 3469 unsigned char *ptr, zero = '\0'; 3470 char *sptr; 3471 int first; 3472 ber_len_t i, len, nlen; 3473 3474 assert( in != NULL ); 3475 assert( !BER_BVISNULL( in ) ); 3476 assert( out != NULL ); 3477 assert( !BER_BVISNULL( out ) ); 3478 3479 ptr = (unsigned char *)in->bv_val; 3480 len = in->bv_len; 3481 3482 /* Check for minimal encodings */ 3483 if ( len > 1 ) { 3484 if ( ptr[0] & 0x80 ) { 3485 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) { 3486 return -1; 3487 } 3488 3489 } else if ( ptr[0] == 0 ) { 3490 if ( !( ptr[1] & 0x80 ) ) { 3491 return -1; 3492 } 3493 len--; 3494 ptr++; 3495 } 3496 3497 } else if ( len == 0 ) { 3498 /* FIXME: this should not be possible, 3499 * since a value of zero would have length 1 */ 3500 len = 1; 3501 ptr = &zero; 3502 } 3503 3504 first = !( ptr[0] & 0xf0U ); 3505 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */ 3506 if ( nlen >= out->bv_len ) { 3507 out->bv_val = slap_sl_malloc( nlen + 1, ctx ); 3508 } 3509 sptr = out->bv_val; 3510 *sptr++ = '\''; 3511 i = 0; 3512 if ( first ) { 3513 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) ); 3514 sptr++; 3515 i = 1; 3516 } 3517 for ( ; i < len; i++ ) { 3518 sprintf( sptr, "%02X", ptr[i] ); 3519 sptr += 2; 3520 } 3521 *sptr++ = '\''; 3522 *sptr++ = 'H'; 3523 *sptr = '\0'; 3524 3525 assert( sptr == &out->bv_val[nlen] ); 3526 3527 out->bv_len = nlen; 3528 3529 return 0; 3530 } 3531 3532 #define SLAP_SN_BUFLEN (64) 3533 3534 /* 3535 * This routine is called by certificateExactNormalize when 3536 * certificateExactNormalize receives a search string instead of 3537 * a certificate. This routine checks if the search value is valid 3538 * and then returns the normalized value 3539 */ 3540 static int 3541 serialNumberAndIssuerNormalize( 3542 slap_mask_t usage, 3543 Syntax *syntax, 3544 MatchingRule *mr, 3545 struct berval *in, 3546 struct berval *out, 3547 void *ctx ) 3548 { 3549 struct berval sn, sn2, sn3, i, ni; 3550 char sbuf2[SLAP_SN_BUFLEN]; 3551 char sbuf3[SLAP_SN_BUFLEN]; 3552 char *p; 3553 int rc; 3554 3555 assert( in != NULL ); 3556 assert( out != NULL ); 3557 3558 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", 3559 in->bv_val, 0, 0 ); 3560 3561 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); 3562 if ( rc ) { 3563 return rc; 3564 } 3565 3566 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 3567 3568 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3569 slap_sl_free( i.bv_val, ctx ); 3570 } 3571 3572 if ( rc ) { 3573 return LDAP_INVALID_SYNTAX; 3574 } 3575 3576 /* Convert sn to canonical hex */ 3577 sn2.bv_val = sbuf2; 3578 if ( sn.bv_len > sizeof( sbuf2 ) ) { 3579 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx ); 3580 } 3581 sn2.bv_len = sn.bv_len; 3582 sn3.bv_val = sbuf3; 3583 sn3.bv_len = sizeof(sbuf3); 3584 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) { 3585 rc = LDAP_INVALID_SYNTAX; 3586 goto func_leave; 3587 } 3588 3589 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3590 + sn3.bv_len + ni.bv_len; 3591 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 3592 if ( out->bv_val == NULL ) { 3593 out->bv_len = 0; 3594 rc = LDAP_OTHER; 3595 goto func_leave; 3596 } 3597 3598 p = out->bv_val; 3599 3600 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3601 p = lutil_strbvcopy( p, &sn3 ); 3602 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3603 p = lutil_strbvcopy( p, &ni ); 3604 p = lutil_strcopy( p, /*{*/ "\" }" ); 3605 3606 assert( p == &out->bv_val[out->bv_len] ); 3607 3608 func_leave: 3609 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n", 3610 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 3611 3612 if ( sn2.bv_val != sbuf2 ) { 3613 slap_sl_free( sn2.bv_val, ctx ); 3614 } 3615 3616 if ( sn3.bv_val != sbuf3 ) { 3617 slap_sl_free( sn3.bv_val, ctx ); 3618 } 3619 3620 slap_sl_free( ni.bv_val, ctx ); 3621 3622 return rc; 3623 } 3624 3625 static int 3626 certificateExactNormalize( 3627 slap_mask_t usage, 3628 Syntax *syntax, 3629 MatchingRule *mr, 3630 struct berval *val, 3631 struct berval *normalized, 3632 void *ctx ) 3633 { 3634 BerElementBuffer berbuf; 3635 BerElement *ber = (BerElement *)&berbuf; 3636 ber_tag_t tag; 3637 ber_len_t len; 3638 ber_int_t i; 3639 char serialbuf2[SLAP_SN_BUFLEN]; 3640 struct berval sn, sn2 = BER_BVNULL; 3641 struct berval issuer_dn = BER_BVNULL, bvdn; 3642 char *p; 3643 int rc = LDAP_INVALID_SYNTAX; 3644 3645 assert( val != NULL ); 3646 3647 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n", 3648 val->bv_val, val->bv_len, 0 ); 3649 3650 if ( BER_BVISEMPTY( val ) ) goto done; 3651 3652 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 3653 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx ); 3654 } 3655 3656 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 3657 3658 ber_init2( ber, val, LBER_USE_DER ); 3659 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 3660 tag = ber_skip_tag( ber, &len ); /* Sequence */ 3661 tag = ber_peek_tag( ber, &len ); /* Optional version? */ 3662 if ( tag == SLAP_X509_OPT_C_VERSION ) { 3663 tag = ber_skip_tag( ber, &len ); 3664 tag = ber_get_int( ber, &i ); /* version */ 3665 } 3666 3667 /* NOTE: move the test here from certificateValidate, 3668 * so that we can validate certs with serial longer 3669 * than sizeof(ber_int_t) */ 3670 tag = ber_skip_tag( ber, &len ); /* serial */ 3671 sn.bv_len = len; 3672 sn.bv_val = (char *)ber->ber_ptr; 3673 sn2.bv_val = serialbuf2; 3674 sn2.bv_len = sizeof(serialbuf2); 3675 if ( slap_bin2hex( &sn, &sn2, ctx ) ) { 3676 rc = LDAP_INVALID_SYNTAX; 3677 goto done; 3678 } 3679 ber_skip_data( ber, len ); 3680 3681 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */ 3682 ber_skip_data( ber, len ); 3683 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 3684 if ( len ) { 3685 len = ber_ptrlen( ber ); 3686 bvdn.bv_val = val->bv_val + len; 3687 bvdn.bv_len = val->bv_len - len; 3688 3689 rc = dnX509normalize( &bvdn, &issuer_dn ); 3690 if ( rc != LDAP_SUCCESS ) { 3691 rc = LDAP_INVALID_SYNTAX; 3692 goto done; 3693 } 3694 } 3695 3696 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) 3697 + sn2.bv_len + issuer_dn.bv_len; 3698 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 3699 3700 p = normalized->bv_val; 3701 3702 p = lutil_strcopy( p, "{ serialNumber " /*}*/ ); 3703 p = lutil_strbvcopy( p, &sn2 ); 3704 p = lutil_strcopy( p, ", issuer rdnSequence:\"" ); 3705 p = lutil_strbvcopy( p, &issuer_dn ); 3706 p = lutil_strcopy( p, /*{*/ "\" }" ); 3707 3708 rc = LDAP_SUCCESS; 3709 3710 done: 3711 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n", 3712 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" ); 3713 3714 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 3715 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx ); 3716 3717 return rc; 3718 } 3719 3720 /* X.509 PKI certificateList stuff */ 3721 static int 3722 checkTime( struct berval *in, struct berval *out ) 3723 { 3724 int rc; 3725 ber_len_t i; 3726 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 3727 struct berval bv; 3728 3729 assert( in != NULL ); 3730 assert( !BER_BVISNULL( in ) ); 3731 assert( !BER_BVISEMPTY( in ) ); 3732 3733 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) { 3734 return -1; 3735 } 3736 3737 if ( out != NULL ) { 3738 assert( !BER_BVISNULL( out ) ); 3739 assert( out->bv_len >= sizeof( buf ) ); 3740 bv.bv_val = out->bv_val; 3741 3742 } else { 3743 bv.bv_val = buf; 3744 } 3745 3746 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) { 3747 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break; 3748 } 3749 3750 if ( in->bv_val[i] != 'Z' ) { 3751 return -1; 3752 } 3753 i++; 3754 3755 if ( i != in->bv_len ) { 3756 return -1; 3757 } 3758 3759 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 3760 lutil_strncopy( bv.bv_val, in->bv_val, i ); 3761 bv.bv_len = i; 3762 3763 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) { 3764 char *p = bv.bv_val; 3765 if ( in->bv_val[0] < '7' ) { 3766 p = lutil_strcopy( p, "20" ); 3767 3768 } else { 3769 p = lutil_strcopy( p, "19" ); 3770 } 3771 lutil_strncopy( p, in->bv_val, i ); 3772 bv.bv_len = 2 + i; 3773 3774 } else { 3775 return -1; 3776 } 3777 3778 rc = generalizedTimeValidate( NULL, &bv ); 3779 if ( rc == LDAP_SUCCESS && out != NULL ) { 3780 if ( out->bv_len > bv.bv_len ) { 3781 out->bv_val[ bv.bv_len ] = '\0'; 3782 } 3783 out->bv_len = bv.bv_len; 3784 } 3785 3786 return rc != LDAP_SUCCESS; 3787 } 3788 3789 static int 3790 issuerAndThisUpdateCheck( 3791 struct berval *in, 3792 struct berval *is, 3793 struct berval *tu, 3794 void *ctx ) 3795 { 3796 int numdquotes = 0; 3797 struct berval x = *in; 3798 struct berval ni = BER_BVNULL; 3799 /* Parse GSER format */ 3800 enum { 3801 HAVE_NONE = 0x0, 3802 HAVE_ISSUER = 0x1, 3803 HAVE_THISUPDATE = 0x2, 3804 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE ) 3805 } have = HAVE_NONE; 3806 3807 3808 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX; 3809 3810 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { 3811 return LDAP_INVALID_SYNTAX; 3812 } 3813 3814 x.bv_val++; 3815 x.bv_len -= STRLENOF("{}"); 3816 3817 do { 3818 /* eat leading spaces */ 3819 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3820 /* empty */; 3821 } 3822 3823 /* should be at issuer or thisUpdate */ 3824 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 3825 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX; 3826 3827 /* parse issuer */ 3828 x.bv_val += STRLENOF("issuer"); 3829 x.bv_len -= STRLENOF("issuer"); 3830 3831 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3832 x.bv_val++; 3833 x.bv_len--; 3834 3835 /* eat leading spaces */ 3836 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3837 /* empty */; 3838 } 3839 3840 /* For backward compatibility, this part is optional */ 3841 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) { 3842 return LDAP_INVALID_SYNTAX; 3843 } 3844 x.bv_val += STRLENOF("rdnSequence:"); 3845 x.bv_len -= STRLENOF("rdnSequence:"); 3846 3847 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3848 x.bv_val++; 3849 x.bv_len--; 3850 3851 is->bv_val = x.bv_val; 3852 is->bv_len = 0; 3853 3854 for ( ; is->bv_len < x.bv_len; ) { 3855 if ( is->bv_val[is->bv_len] != '"' ) { 3856 is->bv_len++; 3857 continue; 3858 } 3859 if ( is->bv_val[is->bv_len+1] == '"' ) { 3860 /* double dquote */ 3861 numdquotes++; 3862 is->bv_len += 2; 3863 continue; 3864 } 3865 break; 3866 } 3867 x.bv_val += is->bv_len + 1; 3868 x.bv_len -= is->bv_len + 1; 3869 3870 have |= HAVE_ISSUER; 3871 3872 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 ) 3873 { 3874 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX; 3875 3876 /* parse thisUpdate */ 3877 x.bv_val += STRLENOF("thisUpdate"); 3878 x.bv_len -= STRLENOF("thisUpdate"); 3879 3880 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 3881 x.bv_val++; 3882 x.bv_len--; 3883 3884 /* eat leading spaces */ 3885 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3886 /* empty */; 3887 } 3888 3889 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 3890 x.bv_val++; 3891 x.bv_len--; 3892 3893 tu->bv_val = x.bv_val; 3894 tu->bv_len = 0; 3895 3896 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) { 3897 if ( tu->bv_val[tu->bv_len] == '"' ) { 3898 break; 3899 } 3900 } 3901 x.bv_val += tu->bv_len + 1; 3902 x.bv_len -= tu->bv_len + 1; 3903 3904 have |= HAVE_THISUPDATE; 3905 3906 } else { 3907 return LDAP_INVALID_SYNTAX; 3908 } 3909 3910 /* eat leading spaces */ 3911 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 3912 /* empty */; 3913 } 3914 3915 if ( have == HAVE_ALL ) { 3916 break; 3917 } 3918 3919 if ( x.bv_val[0] != ',' ) { 3920 return LDAP_INVALID_SYNTAX; 3921 } 3922 3923 x.bv_val++; 3924 x.bv_len--; 3925 } while ( 1 ); 3926 3927 /* should have no characters left... */ 3928 if ( x.bv_len ) return LDAP_INVALID_SYNTAX; 3929 3930 if ( numdquotes == 0 ) { 3931 ber_dupbv_x( &ni, is, ctx ); 3932 3933 } else { 3934 ber_len_t src, dst; 3935 3936 ni.bv_len = is->bv_len - numdquotes; 3937 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 3938 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 3939 if ( is->bv_val[src] == '"' ) { 3940 src++; 3941 } 3942 ni.bv_val[dst] = is->bv_val[src]; 3943 } 3944 ni.bv_val[dst] = '\0'; 3945 } 3946 3947 *is = ni; 3948 3949 return 0; 3950 } 3951 3952 static int 3953 issuerAndThisUpdateValidate( 3954 Syntax *syntax, 3955 struct berval *in ) 3956 { 3957 int rc; 3958 struct berval i, tu; 3959 3960 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n", 3961 in->bv_val, 0, 0 ); 3962 3963 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL ); 3964 if ( rc ) { 3965 goto done; 3966 } 3967 3968 /* validate DN -- doesn't handle double dquote */ 3969 rc = dnValidate( NULL, &i ); 3970 if ( rc ) { 3971 rc = LDAP_INVALID_SYNTAX; 3972 3973 } else if ( checkTime( &tu, NULL ) ) { 3974 rc = LDAP_INVALID_SYNTAX; 3975 } 3976 3977 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 3978 slap_sl_free( i.bv_val, NULL ); 3979 } 3980 3981 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n", 3982 in->bv_val, rc, 0 ); 3983 3984 done:; 3985 return rc; 3986 } 3987 3988 static int 3989 issuerAndThisUpdatePretty( 3990 Syntax *syntax, 3991 struct berval *in, 3992 struct berval *out, 3993 void *ctx ) 3994 { 3995 int rc; 3996 struct berval i, tu, ni = BER_BVNULL; 3997 char *p; 3998 3999 assert( in != NULL ); 4000 assert( out != NULL ); 4001 4002 BER_BVZERO( out ); 4003 4004 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n", 4005 in->bv_val, 0, 0 ); 4006 4007 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx ); 4008 if ( rc ) { 4009 goto done; 4010 } 4011 4012 rc = dnPretty( syntax, &i, &ni, ctx ); 4013 4014 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4015 slap_sl_free( i.bv_val, ctx ); 4016 } 4017 4018 if ( rc || checkTime( &tu, NULL ) ) { 4019 rc = LDAP_INVALID_SYNTAX; 4020 goto done; 4021 } 4022 4023 /* make room */ 4024 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }") 4025 + ni.bv_len + tu.bv_len; 4026 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4027 4028 if ( out->bv_val == NULL ) { 4029 out->bv_len = 0; 4030 rc = LDAP_OTHER; 4031 goto done; 4032 } 4033 4034 p = out->bv_val; 4035 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ ); 4036 p = lutil_strbvcopy( p, &ni ); 4037 p = lutil_strcopy( p, "\", thisUpdate \"" ); 4038 p = lutil_strbvcopy( p, &tu ); 4039 p = lutil_strcopy( p, /*{*/ "\" }" ); 4040 4041 assert( p == &out->bv_val[out->bv_len] ); 4042 4043 done:; 4044 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n", 4045 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4046 4047 slap_sl_free( ni.bv_val, ctx ); 4048 4049 return rc; 4050 } 4051 4052 static int 4053 issuerAndThisUpdateNormalize( 4054 slap_mask_t usage, 4055 Syntax *syntax, 4056 MatchingRule *mr, 4057 struct berval *in, 4058 struct berval *out, 4059 void *ctx ) 4060 { 4061 struct berval i, ni, tu, tu2; 4062 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 4063 char *p; 4064 int rc; 4065 4066 assert( in != NULL ); 4067 assert( out != NULL ); 4068 4069 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n", 4070 in->bv_val, 0, 0 ); 4071 4072 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx ); 4073 if ( rc ) { 4074 return rc; 4075 } 4076 4077 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 4078 4079 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4080 slap_sl_free( i.bv_val, ctx ); 4081 } 4082 4083 tu2.bv_val = sbuf; 4084 tu2.bv_len = sizeof( sbuf ); 4085 if ( rc || checkTime( &tu, &tu2 ) ) { 4086 return LDAP_INVALID_SYNTAX; 4087 } 4088 4089 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" ) 4090 + ni.bv_len + tu2.bv_len; 4091 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4092 4093 if ( out->bv_val == NULL ) { 4094 out->bv_len = 0; 4095 rc = LDAP_OTHER; 4096 goto func_leave; 4097 } 4098 4099 p = out->bv_val; 4100 4101 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ ); 4102 p = lutil_strbvcopy( p, &ni ); 4103 p = lutil_strcopy( p, "\", thisUpdate \"" ); 4104 p = lutil_strbvcopy( p, &tu2 ); 4105 p = lutil_strcopy( p, /*{*/ "\" }" ); 4106 4107 assert( p == &out->bv_val[out->bv_len] ); 4108 4109 func_leave: 4110 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n", 4111 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4112 4113 slap_sl_free( ni.bv_val, ctx ); 4114 4115 return rc; 4116 } 4117 4118 static int 4119 certificateListExactNormalize( 4120 slap_mask_t usage, 4121 Syntax *syntax, 4122 MatchingRule *mr, 4123 struct berval *val, 4124 struct berval *normalized, 4125 void *ctx ) 4126 { 4127 BerElementBuffer berbuf; 4128 BerElement *ber = (BerElement *)&berbuf; 4129 ber_tag_t tag; 4130 ber_len_t len; 4131 ber_int_t version; 4132 struct berval issuer_dn = BER_BVNULL, bvdn, 4133 thisUpdate, bvtu; 4134 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1]; 4135 int rc = LDAP_INVALID_SYNTAX; 4136 4137 assert( val != NULL ); 4138 4139 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n", 4140 val->bv_val, val->bv_len, 0 ); 4141 4142 if ( BER_BVISEMPTY( val ) ) goto done; 4143 4144 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 4145 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx ); 4146 } 4147 4148 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 4149 4150 ber_init2( ber, val, LBER_USE_DER ); 4151 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */ 4152 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4153 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4154 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4155 tag = ber_peek_tag( ber, &len ); 4156 /* Optional version */ 4157 if ( tag == LBER_INTEGER ) { 4158 tag = ber_get_int( ber, &version ); 4159 assert( tag == LBER_INTEGER ); 4160 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; 4161 } 4162 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ 4163 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4164 ber_skip_data( ber, len ); 4165 4166 tag = ber_peek_tag( ber, &len ); /* IssuerDN */ 4167 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; 4168 len = ber_ptrlen( ber ); 4169 bvdn.bv_val = val->bv_val + len; 4170 bvdn.bv_len = val->bv_len - len; 4171 tag = ber_skip_tag( ber, &len ); 4172 ber_skip_data( ber, len ); 4173 4174 tag = ber_skip_tag( ber, &len ); /* thisUpdate */ 4175 /* Time is a CHOICE { UTCTime, GeneralizedTime } */ 4176 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX; 4177 bvtu.bv_val = (char *)ber->ber_ptr; 4178 bvtu.bv_len = len; 4179 4180 rc = dnX509normalize( &bvdn, &issuer_dn ); 4181 if ( rc != LDAP_SUCCESS ) { 4182 rc = LDAP_INVALID_SYNTAX; 4183 goto done; 4184 } 4185 4186 thisUpdate.bv_val = tubuf; 4187 thisUpdate.bv_len = sizeof(tubuf); 4188 if ( checkTime( &bvtu, &thisUpdate ) ) { 4189 rc = LDAP_INVALID_SYNTAX; 4190 goto done; 4191 } 4192 4193 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" ) 4194 + issuer_dn.bv_len + thisUpdate.bv_len; 4195 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 4196 4197 p = normalized->bv_val; 4198 4199 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" ); 4200 p = lutil_strbvcopy( p, &issuer_dn ); 4201 p = lutil_strcopy( p, "\", thisUpdate \"" ); 4202 p = lutil_strbvcopy( p, &thisUpdate ); 4203 p = lutil_strcopy( p, /*{*/ "\" }" ); 4204 4205 rc = LDAP_SUCCESS; 4206 4207 done: 4208 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n", 4209 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" ); 4210 4211 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 4212 4213 return rc; 4214 } 4215 4216 /* X.509 PMI serialNumberAndIssuerSerialCheck 4217 4218 AttributeCertificateExactAssertion ::= SEQUENCE { 4219 serialNumber CertificateSerialNumber, 4220 issuer AttCertIssuer } 4221 4222 CertificateSerialNumber ::= INTEGER 4223 4224 AttCertIssuer ::= [0] SEQUENCE { 4225 issuerName GeneralNames OPTIONAL, 4226 baseCertificateID [0] IssuerSerial OPTIONAL, 4227 objectDigestInfo [1] ObjectDigestInfo OPTIONAL } 4228 -- At least one component shall be present 4229 4230 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 4231 4232 GeneralName ::= CHOICE { 4233 otherName [0] INSTANCE OF OTHER-NAME, 4234 rfc822Name [1] IA5String, 4235 dNSName [2] IA5String, 4236 x400Address [3] ORAddress, 4237 directoryName [4] Name, 4238 ediPartyName [5] EDIPartyName, 4239 uniformResourceIdentifier [6] IA5String, 4240 iPAddress [7] OCTET STRING, 4241 registeredID [8] OBJECT IDENTIFIER } 4242 4243 IssuerSerial ::= SEQUENCE { 4244 issuer GeneralNames, 4245 serial CertificateSerialNumber, 4246 issuerUID UniqueIdentifier OPTIONAL } 4247 4248 ObjectDigestInfo ::= SEQUENCE { 4249 digestedObjectType ENUMERATED { 4250 publicKey (0), 4251 publicKeyCert (1), 4252 otherObjectTypes (2) }, 4253 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL, 4254 digestAlgorithm AlgorithmIdentifier, 4255 objectDigest BIT STRING } 4256 4257 * The way I interpret it, an assertion should look like 4258 4259 { serialNumber 'dd'H, 4260 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional 4261 baseCertificateID { serial '1d'H, 4262 issuer { directoryName:rdnSequence:"cn=zzz" }, 4263 issuerUID <value> -- optional 4264 }, -- optional 4265 objectDigestInfo { ... } -- optional 4266 } 4267 } 4268 4269 * with issuerName, baseCertificateID and objectDigestInfo optional, 4270 * at least one present; the way it's currently implemented, it is 4271 4272 { serialNumber 'dd'H, 4273 issuer { baseCertificateID { serial '1d'H, 4274 issuer { directoryName:rdnSequence:"cn=zzz" } 4275 } 4276 } 4277 } 4278 4279 * with all the above parts mandatory. 4280 */ 4281 static int 4282 serialNumberAndIssuerSerialCheck( 4283 struct berval *in, 4284 struct berval *sn, 4285 struct berval *is, 4286 struct berval *i_sn, /* contain serial of baseCertificateID */ 4287 void *ctx ) 4288 { 4289 /* Parse GSER format */ 4290 enum { 4291 HAVE_NONE = 0x0, 4292 HAVE_SN = 0x1, 4293 HAVE_ISSUER = 0x2, 4294 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER ) 4295 } have = HAVE_NONE, have2 = HAVE_NONE; 4296 int numdquotes = 0; 4297 struct berval x = *in; 4298 struct berval ni; 4299 4300 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 4301 4302 /* no old format */ 4303 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX; 4304 4305 x.bv_val++; 4306 x.bv_len -= 2; 4307 4308 do { 4309 4310 /* eat leading spaces */ 4311 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4312 /* empty */; 4313 } 4314 4315 /* should be at issuer or serialNumber NamedValue */ 4316 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) { 4317 if ( have & HAVE_ISSUER ) { 4318 return LDAP_INVALID_SYNTAX; 4319 } 4320 4321 /* parse IssuerSerial */ 4322 x.bv_val += STRLENOF("issuer"); 4323 x.bv_len -= STRLENOF("issuer"); 4324 4325 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 4326 x.bv_val++; 4327 x.bv_len--; 4328 4329 /* eat leading spaces */ 4330 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4331 /* empty */; 4332 } 4333 4334 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4335 x.bv_val++; 4336 x.bv_len--; 4337 4338 /* eat leading spaces */ 4339 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4340 /* empty */; 4341 } 4342 4343 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) { 4344 return LDAP_INVALID_SYNTAX; 4345 } 4346 x.bv_val += STRLENOF("baseCertificateID "); 4347 x.bv_len -= STRLENOF("baseCertificateID "); 4348 4349 /* eat leading spaces */ 4350 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4351 /* empty */; 4352 } 4353 4354 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4355 x.bv_val++; 4356 x.bv_len--; 4357 4358 do { 4359 /* eat leading spaces */ 4360 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4361 /* empty */; 4362 } 4363 4364 /* parse issuer of baseCertificateID */ 4365 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) { 4366 if ( have2 & HAVE_ISSUER ) { 4367 return LDAP_INVALID_SYNTAX; 4368 } 4369 4370 x.bv_val += STRLENOF("issuer "); 4371 x.bv_len -= STRLENOF("issuer "); 4372 4373 /* eat leading spaces */ 4374 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4375 /* empty */; 4376 } 4377 4378 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX; 4379 x.bv_val++; 4380 x.bv_len--; 4381 4382 /* eat leading spaces */ 4383 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4384 /* empty */; 4385 } 4386 4387 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) { 4388 return LDAP_INVALID_SYNTAX; 4389 } 4390 x.bv_val += STRLENOF("directoryName:rdnSequence:"); 4391 x.bv_len -= STRLENOF("directoryName:rdnSequence:"); 4392 4393 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX; 4394 x.bv_val++; 4395 x.bv_len--; 4396 4397 is->bv_val = x.bv_val; 4398 is->bv_len = 0; 4399 4400 for ( ; is->bv_len < x.bv_len; ) { 4401 if ( is->bv_val[is->bv_len] != '"' ) { 4402 is->bv_len++; 4403 continue; 4404 } 4405 if ( is->bv_val[is->bv_len + 1] == '"' ) { 4406 /* double dquote */ 4407 numdquotes++; 4408 is->bv_len += 2; 4409 continue; 4410 } 4411 break; 4412 } 4413 x.bv_val += is->bv_len + 1; 4414 x.bv_len -= is->bv_len + 1; 4415 4416 /* eat leading spaces */ 4417 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4418 /* empty */; 4419 } 4420 4421 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4422 x.bv_val++; 4423 x.bv_len--; 4424 4425 have2 |= HAVE_ISSUER; 4426 4427 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) { 4428 if ( have2 & HAVE_SN ) { 4429 return LDAP_INVALID_SYNTAX; 4430 } 4431 4432 x.bv_val += STRLENOF("serial "); 4433 x.bv_len -= STRLENOF("serial "); 4434 4435 /* eat leading spaces */ 4436 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { 4437 /* empty */; 4438 } 4439 4440 if ( checkNum( &x, i_sn ) ) { 4441 return LDAP_INVALID_SYNTAX; 4442 } 4443 4444 x.bv_val += i_sn->bv_len; 4445 x.bv_len -= i_sn->bv_len; 4446 4447 have2 |= HAVE_SN; 4448 4449 } else { 4450 return LDAP_INVALID_SYNTAX; 4451 } 4452 4453 /* eat leading spaces */ 4454 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4455 /* empty */; 4456 } 4457 4458 if ( have2 == HAVE_ALL ) { 4459 break; 4460 } 4461 4462 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX; 4463 x.bv_val++; 4464 x.bv_len--; 4465 } while ( 1 ); 4466 4467 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4468 x.bv_val++; 4469 x.bv_len--; 4470 4471 /* eat leading spaces */ 4472 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4473 /* empty */; 4474 } 4475 4476 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX; 4477 x.bv_val++; 4478 x.bv_len--; 4479 4480 have |= HAVE_ISSUER; 4481 4482 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) { 4483 if ( have & HAVE_SN ) { 4484 return LDAP_INVALID_SYNTAX; 4485 } 4486 4487 /* parse serialNumber */ 4488 x.bv_val += STRLENOF("serialNumber"); 4489 x.bv_len -= STRLENOF("serialNumber"); 4490 4491 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX; 4492 x.bv_val++; 4493 x.bv_len--; 4494 4495 /* eat leading spaces */ 4496 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4497 /* empty */; 4498 } 4499 4500 if ( checkNum( &x, sn ) ) { 4501 return LDAP_INVALID_SYNTAX; 4502 } 4503 4504 x.bv_val += sn->bv_len; 4505 x.bv_len -= sn->bv_len; 4506 4507 have |= HAVE_SN; 4508 4509 } else { 4510 return LDAP_INVALID_SYNTAX; 4511 } 4512 4513 /* eat spaces */ 4514 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) { 4515 /* empty */; 4516 } 4517 4518 if ( have == HAVE_ALL ) { 4519 break; 4520 } 4521 4522 if ( x.bv_val[0] != ',' ) { 4523 return LDAP_INVALID_SYNTAX; 4524 } 4525 x.bv_val++ ; 4526 x.bv_len--; 4527 } while ( 1 ); 4528 4529 /* should have no characters left... */ 4530 if( x.bv_len ) return LDAP_INVALID_SYNTAX; 4531 4532 if ( numdquotes == 0 ) { 4533 ber_dupbv_x( &ni, is, ctx ); 4534 4535 } else { 4536 ber_len_t src, dst; 4537 4538 ni.bv_len = is->bv_len - numdquotes; 4539 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx ); 4540 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) { 4541 if ( is->bv_val[src] == '"' ) { 4542 src++; 4543 } 4544 ni.bv_val[dst] = is->bv_val[src]; 4545 } 4546 ni.bv_val[dst] = '\0'; 4547 } 4548 4549 *is = ni; 4550 4551 /* need to handle double dquotes here */ 4552 return 0; 4553 } 4554 4555 /* X.509 PMI serialNumberAndIssuerSerialValidate */ 4556 static int 4557 serialNumberAndIssuerSerialValidate( 4558 Syntax *syntax, 4559 struct berval *in ) 4560 { 4561 int rc; 4562 struct berval sn, i, i_sn; 4563 4564 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n", 4565 in->bv_val, 0, 0 ); 4566 4567 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL ); 4568 if ( rc ) { 4569 goto done; 4570 } 4571 4572 /* validate DN -- doesn't handle double dquote */ 4573 rc = dnValidate( NULL, &i ); 4574 if ( rc ) { 4575 rc = LDAP_INVALID_SYNTAX; 4576 } 4577 4578 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4579 slap_sl_free( i.bv_val, NULL ); 4580 } 4581 4582 done:; 4583 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n", 4584 in->bv_val, rc, 0 ); 4585 4586 return rc; 4587 } 4588 4589 /* X.509 PMI serialNumberAndIssuerSerialPretty */ 4590 static int 4591 serialNumberAndIssuerSerialPretty( 4592 Syntax *syntax, 4593 struct berval *in, 4594 struct berval *out, 4595 void *ctx ) 4596 { 4597 struct berval sn, i, i_sn, ni = BER_BVNULL; 4598 char *p; 4599 int rc; 4600 4601 assert( in != NULL ); 4602 assert( out != NULL ); 4603 4604 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n", 4605 in->bv_val, 0, 0 ); 4606 4607 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx ); 4608 if ( rc ) { 4609 goto done; 4610 } 4611 4612 rc = dnPretty( syntax, &i, &ni, ctx ); 4613 4614 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4615 slap_sl_free( i.bv_val, ctx ); 4616 } 4617 4618 if ( rc ) { 4619 rc = LDAP_INVALID_SYNTAX; 4620 goto done; 4621 } 4622 4623 /* make room from sn + "$" */ 4624 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }") 4625 + sn.bv_len + ni.bv_len + i_sn.bv_len; 4626 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4627 4628 if ( out->bv_val == NULL ) { 4629 out->bv_len = 0; 4630 rc = LDAP_OTHER; 4631 goto done; 4632 } 4633 4634 p = out->bv_val; 4635 p = lutil_strcopy( p, "{ serialNumber " ); 4636 p = lutil_strbvcopy( p, &sn ); 4637 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4638 p = lutil_strbvcopy( p, &ni ); 4639 p = lutil_strcopy( p, "\" }, serial " ); 4640 p = lutil_strbvcopy( p, &i_sn ); 4641 p = lutil_strcopy( p, " } } }" ); 4642 4643 assert( p == &out->bv_val[out->bv_len] ); 4644 4645 done:; 4646 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n", 4647 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4648 4649 slap_sl_free( ni.bv_val, ctx ); 4650 4651 return rc; 4652 } 4653 4654 /* X.509 PMI serialNumberAndIssuerSerialNormalize */ 4655 /* 4656 * This routine is called by attributeCertificateExactNormalize 4657 * when attributeCertificateExactNormalize receives a search 4658 * string instead of a attribute certificate. This routine 4659 * checks if the search value is valid and then returns the 4660 * normalized value 4661 */ 4662 static int 4663 serialNumberAndIssuerSerialNormalize( 4664 slap_mask_t usage, 4665 Syntax *syntax, 4666 MatchingRule *mr, 4667 struct berval *in, 4668 struct berval *out, 4669 void *ctx ) 4670 { 4671 struct berval i, ni = BER_BVNULL, 4672 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL, 4673 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL; 4674 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN], 4675 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN]; 4676 char *p; 4677 int rc; 4678 4679 assert( in != NULL ); 4680 assert( out != NULL ); 4681 4682 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n", 4683 in->bv_val, 0, 0 ); 4684 4685 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx ); 4686 if ( rc ) { 4687 goto func_leave; 4688 } 4689 4690 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx ); 4691 4692 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) { 4693 slap_sl_free( i.bv_val, ctx ); 4694 } 4695 4696 if ( rc ) { 4697 rc = LDAP_INVALID_SYNTAX; 4698 goto func_leave; 4699 } 4700 4701 /* Convert sn to canonical hex */ 4702 sn2.bv_val = sbuf2; 4703 sn2.bv_len = sn.bv_len; 4704 if ( sn.bv_len > sizeof( sbuf2 ) ) { 4705 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx ); 4706 } 4707 if ( lutil_str2bin( &sn, &sn2, ctx ) ) { 4708 rc = LDAP_INVALID_SYNTAX; 4709 goto func_leave; 4710 } 4711 4712 /* Convert i_sn to canonical hex */ 4713 i_sn2.bv_val = i_sbuf2; 4714 i_sn2.bv_len = i_sn.bv_len; 4715 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) { 4716 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx ); 4717 } 4718 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) { 4719 rc = LDAP_INVALID_SYNTAX; 4720 goto func_leave; 4721 } 4722 4723 sn3.bv_val = sbuf3; 4724 sn3.bv_len = sizeof(sbuf3); 4725 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) { 4726 rc = LDAP_INVALID_SYNTAX; 4727 goto func_leave; 4728 } 4729 4730 i_sn3.bv_val = i_sbuf3; 4731 i_sn3.bv_len = sizeof(i_sbuf3); 4732 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) { 4733 rc = LDAP_INVALID_SYNTAX; 4734 goto func_leave; 4735 } 4736 4737 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }") 4738 + sn3.bv_len + ni.bv_len + i_sn3.bv_len; 4739 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); 4740 4741 if ( out->bv_val == NULL ) { 4742 out->bv_len = 0; 4743 rc = LDAP_OTHER; 4744 goto func_leave; 4745 } 4746 4747 p = out->bv_val; 4748 4749 p = lutil_strcopy( p, "{ serialNumber " ); 4750 p = lutil_strbvcopy( p, &sn3 ); 4751 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4752 p = lutil_strbvcopy( p, &ni ); 4753 p = lutil_strcopy( p, "\" }, serial " ); 4754 p = lutil_strbvcopy( p, &i_sn3 ); 4755 p = lutil_strcopy( p, " } } }" ); 4756 4757 assert( p == &out->bv_val[out->bv_len] ); 4758 4759 func_leave: 4760 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n", 4761 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 ); 4762 4763 if ( sn2.bv_val != sbuf2 ) { 4764 slap_sl_free( sn2.bv_val, ctx ); 4765 } 4766 4767 if ( i_sn2.bv_val != i_sbuf2 ) { 4768 slap_sl_free( i_sn2.bv_val, ctx ); 4769 } 4770 4771 if ( sn3.bv_val != sbuf3 ) { 4772 slap_sl_free( sn3.bv_val, ctx ); 4773 } 4774 4775 if ( i_sn3.bv_val != i_sbuf3 ) { 4776 slap_sl_free( i_sn3.bv_val, ctx ); 4777 } 4778 4779 slap_sl_free( ni.bv_val, ctx ); 4780 4781 return rc; 4782 } 4783 4784 /* X.509 PMI attributeCertificateExactNormalize */ 4785 static int 4786 attributeCertificateExactNormalize( 4787 slap_mask_t usage, 4788 Syntax *syntax, 4789 MatchingRule *mr, 4790 struct berval *val, 4791 struct berval *normalized, 4792 void *ctx ) 4793 { 4794 BerElementBuffer berbuf; 4795 BerElement *ber = (BerElement *)&berbuf; 4796 ber_tag_t tag; 4797 ber_len_t len; 4798 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN]; 4799 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL; 4800 struct berval issuer_dn = BER_BVNULL, bvdn; 4801 char *p; 4802 int rc = LDAP_INVALID_SYNTAX; 4803 4804 if ( BER_BVISEMPTY( val ) ) { 4805 return rc; 4806 } 4807 4808 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 4809 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx ); 4810 } 4811 4812 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 4813 4814 ber_init2( ber, val, LBER_USE_DER ); 4815 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */ 4816 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4817 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */ 4818 ber_skip_data( ber, len ); 4819 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */ 4820 ber_skip_data( ber, len ); 4821 4822 /* Issuer */ 4823 tag = ber_skip_tag( ber, &len ); /* Sequence */ 4824 /* issuerName (GeneralNames sequence; optional)? */ 4825 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */ 4826 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */ 4827 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */ 4828 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) { 4829 return LDAP_INVALID_SYNTAX; 4830 } 4831 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */ 4832 len = ber_ptrlen( ber ); 4833 bvdn.bv_val = val->bv_val + len; 4834 bvdn.bv_len = val->bv_len - len; 4835 rc = dnX509normalize( &bvdn, &issuer_dn ); 4836 if ( rc != LDAP_SUCCESS ) { 4837 rc = LDAP_INVALID_SYNTAX; 4838 goto done; 4839 } 4840 4841 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */ 4842 ber_skip_data( ber, len ); 4843 tag = ber_skip_tag( ber, &len ); /* serial number */ 4844 if ( tag != LBER_INTEGER ) { 4845 rc = LDAP_INVALID_SYNTAX; 4846 goto done; 4847 } 4848 i_sn.bv_val = (char *)ber->ber_ptr; 4849 i_sn.bv_len = len; 4850 i_sn2.bv_val = issuer_serialbuf; 4851 i_sn2.bv_len = sizeof(issuer_serialbuf); 4852 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) { 4853 rc = LDAP_INVALID_SYNTAX; 4854 goto done; 4855 } 4856 ber_skip_data( ber, len ); 4857 4858 /* issuerUID (bitstring; optional)? */ 4859 /* objectDigestInfo (sequence; optional)? */ 4860 4861 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */ 4862 ber_skip_data( ber, len ); 4863 tag = ber_skip_tag( ber, &len ); /* serial number */ 4864 if ( tag != LBER_INTEGER ) { 4865 rc = LDAP_INVALID_SYNTAX; 4866 goto done; 4867 } 4868 sn.bv_val = (char *)ber->ber_ptr; 4869 sn.bv_len = len; 4870 sn2.bv_val = serialbuf; 4871 sn2.bv_len = sizeof(serialbuf); 4872 if ( slap_bin2hex( &sn, &sn2, ctx ) ) { 4873 rc = LDAP_INVALID_SYNTAX; 4874 goto done; 4875 } 4876 ber_skip_data( ber, len ); 4877 4878 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" ) 4879 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len; 4880 normalized->bv_val = ch_malloc( normalized->bv_len + 1 ); 4881 4882 p = normalized->bv_val; 4883 4884 p = lutil_strcopy( p, "{ serialNumber " ); 4885 p = lutil_strbvcopy( p, &sn2 ); 4886 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" ); 4887 p = lutil_strbvcopy( p, &issuer_dn ); 4888 p = lutil_strcopy( p, "\" }, serial " ); 4889 p = lutil_strbvcopy( p, &i_sn2 ); 4890 p = lutil_strcopy( p, " } } }" ); 4891 4892 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n", 4893 normalized->bv_val, NULL, NULL ); 4894 4895 rc = LDAP_SUCCESS; 4896 4897 done: 4898 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); 4899 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx ); 4900 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx ); 4901 4902 return rc; 4903 } 4904 4905 4906 static int 4907 hexValidate( 4908 Syntax *syntax, 4909 struct berval *in ) 4910 { 4911 ber_len_t i; 4912 4913 assert( in != NULL ); 4914 assert( !BER_BVISNULL( in ) ); 4915 4916 for ( i = 0; i < in->bv_len; i++ ) { 4917 if ( !ASCII_HEX( in->bv_val[ i ] ) ) { 4918 return LDAP_INVALID_SYNTAX; 4919 } 4920 } 4921 4922 return LDAP_SUCCESS; 4923 } 4924 4925 /* Normalize a SID as used inside a CSN: 4926 * three-digit numeric string */ 4927 static int 4928 hexNormalize( 4929 slap_mask_t usage, 4930 Syntax *syntax, 4931 MatchingRule *mr, 4932 struct berval *val, 4933 struct berval *normalized, 4934 void *ctx ) 4935 { 4936 ber_len_t i; 4937 4938 assert( val != NULL ); 4939 assert( normalized != NULL ); 4940 4941 ber_dupbv_x( normalized, val, ctx ); 4942 4943 for ( i = 0; i < normalized->bv_len; i++ ) { 4944 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) { 4945 ber_memfree_x( normalized->bv_val, ctx ); 4946 BER_BVZERO( normalized ); 4947 return LDAP_INVALID_SYNTAX; 4948 } 4949 4950 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 4951 } 4952 4953 return LDAP_SUCCESS; 4954 } 4955 4956 static int 4957 sidValidate ( 4958 Syntax *syntax, 4959 struct berval *in ) 4960 { 4961 assert( in != NULL ); 4962 assert( !BER_BVISNULL( in ) ); 4963 4964 if ( in->bv_len != 3 ) { 4965 return LDAP_INVALID_SYNTAX; 4966 } 4967 4968 return hexValidate( NULL, in ); 4969 } 4970 4971 /* Normalize a SID as used inside a CSN: 4972 * three-digit numeric string */ 4973 static int 4974 sidNormalize( 4975 slap_mask_t usage, 4976 Syntax *syntax, 4977 MatchingRule *mr, 4978 struct berval *val, 4979 struct berval *normalized, 4980 void *ctx ) 4981 { 4982 if ( val->bv_len != 3 ) { 4983 return LDAP_INVALID_SYNTAX; 4984 } 4985 4986 return hexNormalize( 0, NULL, NULL, val, normalized, ctx ); 4987 } 4988 4989 static int 4990 sidPretty( 4991 Syntax *syntax, 4992 struct berval *val, 4993 struct berval *out, 4994 void *ctx ) 4995 { 4996 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 4997 } 4998 4999 /* Normalize a SID as used inside a CSN, either as-is 5000 * (assertion value) or extracted from the CSN 5001 * (attribute value) */ 5002 static int 5003 csnSidNormalize( 5004 slap_mask_t usage, 5005 Syntax *syntax, 5006 MatchingRule *mr, 5007 struct berval *val, 5008 struct berval *normalized, 5009 void *ctx ) 5010 { 5011 struct berval bv; 5012 char *ptr, 5013 buf[ 4 ]; 5014 5015 5016 if ( BER_BVISEMPTY( val ) ) { 5017 return LDAP_INVALID_SYNTAX; 5018 } 5019 5020 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { 5021 return sidNormalize( 0, NULL, NULL, val, normalized, ctx ); 5022 } 5023 5024 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); 5025 5026 ptr = ber_bvchr( val, '#' ); 5027 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5028 return LDAP_INVALID_SYNTAX; 5029 } 5030 5031 bv.bv_val = ptr + 1; 5032 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 5033 5034 ptr = ber_bvchr( &bv, '#' ); 5035 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5036 return LDAP_INVALID_SYNTAX; 5037 } 5038 5039 bv.bv_val = ptr + 1; 5040 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val ); 5041 5042 ptr = ber_bvchr( &bv, '#' ); 5043 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5044 return LDAP_INVALID_SYNTAX; 5045 } 5046 5047 bv.bv_len = ptr - bv.bv_val; 5048 5049 if ( bv.bv_len == 2 ) { 5050 /* OpenLDAP 2.3 SID */ 5051 buf[ 0 ] = '0'; 5052 buf[ 1 ] = bv.bv_val[ 0 ]; 5053 buf[ 2 ] = bv.bv_val[ 1 ]; 5054 buf[ 3 ] = '\0'; 5055 5056 bv.bv_val = buf; 5057 bv.bv_len = 3; 5058 } 5059 5060 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx ); 5061 } 5062 5063 static int 5064 csnValidate( 5065 Syntax *syntax, 5066 struct berval *in ) 5067 { 5068 struct berval bv; 5069 char *ptr; 5070 int rc; 5071 5072 assert( in != NULL ); 5073 assert( !BER_BVISNULL( in ) ); 5074 5075 if ( BER_BVISEMPTY( in ) ) { 5076 return LDAP_INVALID_SYNTAX; 5077 } 5078 5079 bv = *in; 5080 5081 ptr = ber_bvchr( &bv, '#' ); 5082 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) { 5083 return LDAP_INVALID_SYNTAX; 5084 } 5085 5086 bv.bv_len = ptr - bv.bv_val; 5087 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) && 5088 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) 5089 { 5090 return LDAP_INVALID_SYNTAX; 5091 } 5092 5093 rc = generalizedTimeValidate( NULL, &bv ); 5094 if ( rc != LDAP_SUCCESS ) { 5095 return rc; 5096 } 5097 5098 bv.bv_val = ptr + 1; 5099 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 5100 5101 ptr = ber_bvchr( &bv, '#' ); 5102 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) { 5103 return LDAP_INVALID_SYNTAX; 5104 } 5105 5106 bv.bv_len = ptr - bv.bv_val; 5107 if ( bv.bv_len != 6 ) { 5108 return LDAP_INVALID_SYNTAX; 5109 } 5110 5111 rc = hexValidate( NULL, &bv ); 5112 if ( rc != LDAP_SUCCESS ) { 5113 return rc; 5114 } 5115 5116 bv.bv_val = ptr + 1; 5117 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 5118 5119 ptr = ber_bvchr( &bv, '#' ); 5120 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) { 5121 return LDAP_INVALID_SYNTAX; 5122 } 5123 5124 bv.bv_len = ptr - bv.bv_val; 5125 if ( bv.bv_len == 2 ) { 5126 /* tolerate old 2-digit replica-id */ 5127 rc = hexValidate( NULL, &bv ); 5128 5129 } else { 5130 rc = sidValidate( NULL, &bv ); 5131 } 5132 if ( rc != LDAP_SUCCESS ) { 5133 return rc; 5134 } 5135 5136 bv.bv_val = ptr + 1; 5137 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); 5138 5139 if ( bv.bv_len != 6 ) { 5140 return LDAP_INVALID_SYNTAX; 5141 } 5142 5143 return hexValidate( NULL, &bv ); 5144 } 5145 5146 /* Normalize a CSN in OpenLDAP 2.1 format */ 5147 static int 5148 csnNormalize21( 5149 slap_mask_t usage, 5150 Syntax *syntax, 5151 MatchingRule *mr, 5152 struct berval *val, 5153 struct berval *normalized, 5154 void *ctx ) 5155 { 5156 struct berval gt, cnt, sid, mod; 5157 struct berval bv; 5158 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 5159 char *ptr; 5160 ber_len_t i; 5161 5162 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5163 assert( !BER_BVISEMPTY( val ) ); 5164 5165 gt = *val; 5166 5167 ptr = ber_bvchr( >, '#' ); 5168 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) { 5169 return LDAP_INVALID_SYNTAX; 5170 } 5171 5172 gt.bv_len = ptr - gt.bv_val; 5173 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) { 5174 return LDAP_INVALID_SYNTAX; 5175 } 5176 5177 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) { 5178 return LDAP_INVALID_SYNTAX; 5179 } 5180 5181 cnt.bv_val = ptr + 1; 5182 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5183 5184 ptr = ber_bvchr( &cnt, '#' ); 5185 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5186 return LDAP_INVALID_SYNTAX; 5187 } 5188 5189 cnt.bv_len = ptr - cnt.bv_val; 5190 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) { 5191 return LDAP_INVALID_SYNTAX; 5192 } 5193 5194 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) { 5195 return LDAP_INVALID_SYNTAX; 5196 } 5197 5198 cnt.bv_val += STRLENOF( "0x" ); 5199 cnt.bv_len -= STRLENOF( "0x" ); 5200 5201 sid.bv_val = ptr + 1; 5202 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5203 5204 ptr = ber_bvchr( &sid, '#' ); 5205 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5206 return LDAP_INVALID_SYNTAX; 5207 } 5208 5209 sid.bv_len = ptr - sid.bv_val; 5210 if ( sid.bv_len != STRLENOF( "0" ) ) { 5211 return LDAP_INVALID_SYNTAX; 5212 } 5213 5214 mod.bv_val = ptr + 1; 5215 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5216 if ( mod.bv_len != STRLENOF( "0000" ) ) { 5217 return LDAP_INVALID_SYNTAX; 5218 } 5219 5220 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 5221 bv.bv_val = buf; 5222 5223 ptr = bv.bv_val; 5224 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) ); 5225 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ], 5226 STRLENOF( "MM" ) ); 5227 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ], 5228 STRLENOF( "SS" ) ); 5229 ptr = lutil_strcopy( ptr, ".000000Z#00" ); 5230 ptr = lutil_strbvcopy( ptr, &cnt ); 5231 *ptr++ = '#'; 5232 *ptr++ = '0'; 5233 *ptr++ = '0'; 5234 *ptr++ = sid.bv_val[ 0 ]; 5235 *ptr++ = '#'; 5236 *ptr++ = '0'; 5237 *ptr++ = '0'; 5238 for ( i = 0; i < mod.bv_len; i++ ) { 5239 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 5240 } 5241 *ptr = '\0'; 5242 5243 assert( ptr == &bv.bv_val[bv.bv_len] ); 5244 5245 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 5246 return LDAP_INVALID_SYNTAX; 5247 } 5248 5249 ber_dupbv_x( normalized, &bv, ctx ); 5250 5251 return LDAP_SUCCESS; 5252 } 5253 5254 /* Normalize a CSN in OpenLDAP 2.3 format */ 5255 static int 5256 csnNormalize23( 5257 slap_mask_t usage, 5258 Syntax *syntax, 5259 MatchingRule *mr, 5260 struct berval *val, 5261 struct berval *normalized, 5262 void *ctx ) 5263 { 5264 struct berval gt, cnt, sid, mod; 5265 struct berval bv; 5266 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ]; 5267 char *ptr; 5268 ber_len_t i; 5269 5270 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5271 assert( !BER_BVISEMPTY( val ) ); 5272 5273 gt = *val; 5274 5275 ptr = ber_bvchr( >, '#' ); 5276 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) { 5277 return LDAP_INVALID_SYNTAX; 5278 } 5279 5280 gt.bv_len = ptr - gt.bv_val; 5281 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) { 5282 return LDAP_INVALID_SYNTAX; 5283 } 5284 5285 cnt.bv_val = ptr + 1; 5286 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5287 5288 ptr = ber_bvchr( &cnt, '#' ); 5289 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5290 return LDAP_INVALID_SYNTAX; 5291 } 5292 5293 cnt.bv_len = ptr - cnt.bv_val; 5294 if ( cnt.bv_len != STRLENOF( "000000" ) ) { 5295 return LDAP_INVALID_SYNTAX; 5296 } 5297 5298 sid.bv_val = ptr + 1; 5299 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5300 5301 ptr = ber_bvchr( &sid, '#' ); 5302 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5303 return LDAP_INVALID_SYNTAX; 5304 } 5305 5306 sid.bv_len = ptr - sid.bv_val; 5307 if ( sid.bv_len != STRLENOF( "00" ) ) { 5308 return LDAP_INVALID_SYNTAX; 5309 } 5310 5311 mod.bv_val = ptr + 1; 5312 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5313 if ( mod.bv_len != STRLENOF( "000000" ) ) { 5314 return LDAP_INVALID_SYNTAX; 5315 } 5316 5317 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); 5318 bv.bv_val = buf; 5319 5320 ptr = bv.bv_val; 5321 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 ); 5322 ptr = lutil_strcopy( ptr, ".000000Z#" ); 5323 ptr = lutil_strbvcopy( ptr, &cnt ); 5324 *ptr++ = '#'; 5325 *ptr++ = '0'; 5326 for ( i = 0; i < sid.bv_len; i++ ) { 5327 *ptr++ = TOLOWER( sid.bv_val[ i ] ); 5328 } 5329 *ptr++ = '#'; 5330 for ( i = 0; i < mod.bv_len; i++ ) { 5331 *ptr++ = TOLOWER( mod.bv_val[ i ] ); 5332 } 5333 *ptr = '\0'; 5334 5335 assert( ptr == &bv.bv_val[bv.bv_len] ); 5336 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { 5337 return LDAP_INVALID_SYNTAX; 5338 } 5339 5340 ber_dupbv_x( normalized, &bv, ctx ); 5341 5342 return LDAP_SUCCESS; 5343 } 5344 5345 /* Normalize a CSN */ 5346 static int 5347 csnNormalize( 5348 slap_mask_t usage, 5349 Syntax *syntax, 5350 MatchingRule *mr, 5351 struct berval *val, 5352 struct berval *normalized, 5353 void *ctx ) 5354 { 5355 struct berval cnt, sid, mod; 5356 char *ptr; 5357 ber_len_t i; 5358 5359 assert( val != NULL ); 5360 assert( normalized != NULL ); 5361 5362 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); 5363 5364 if ( BER_BVISEMPTY( val ) ) { 5365 return LDAP_INVALID_SYNTAX; 5366 } 5367 5368 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) { 5369 /* Openldap <= 2.3 */ 5370 5371 return csnNormalize23( usage, syntax, mr, val, normalized, ctx ); 5372 } 5373 5374 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) { 5375 /* Openldap 2.1 */ 5376 5377 return csnNormalize21( usage, syntax, mr, val, normalized, ctx ); 5378 } 5379 5380 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) { 5381 return LDAP_INVALID_SYNTAX; 5382 } 5383 5384 ptr = ber_bvchr( val, '#' ); 5385 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5386 return LDAP_INVALID_SYNTAX; 5387 } 5388 5389 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) { 5390 return LDAP_INVALID_SYNTAX; 5391 } 5392 5393 cnt.bv_val = ptr + 1; 5394 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); 5395 5396 ptr = ber_bvchr( &cnt, '#' ); 5397 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5398 return LDAP_INVALID_SYNTAX; 5399 } 5400 5401 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) { 5402 return LDAP_INVALID_SYNTAX; 5403 } 5404 5405 sid.bv_val = ptr + 1; 5406 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val ); 5407 5408 ptr = ber_bvchr( &sid, '#' ); 5409 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) { 5410 return LDAP_INVALID_SYNTAX; 5411 } 5412 5413 sid.bv_len = ptr - sid.bv_val; 5414 if ( sid.bv_len != STRLENOF( "000" ) ) { 5415 return LDAP_INVALID_SYNTAX; 5416 } 5417 5418 mod.bv_val = ptr + 1; 5419 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); 5420 5421 if ( mod.bv_len != STRLENOF( "000000" ) ) { 5422 return LDAP_INVALID_SYNTAX; 5423 } 5424 5425 ber_dupbv_x( normalized, val, ctx ); 5426 5427 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" ); 5428 i < normalized->bv_len; i++ ) 5429 { 5430 /* assume it's already validated that's all hex digits */ 5431 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); 5432 } 5433 5434 return LDAP_SUCCESS; 5435 } 5436 5437 static int 5438 csnPretty( 5439 Syntax *syntax, 5440 struct berval *val, 5441 struct berval *out, 5442 void *ctx ) 5443 { 5444 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); 5445 } 5446 5447 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX 5448 /* slight optimization - does not need the start parameter */ 5449 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f) 5450 enum { start = 0 }; 5451 #endif 5452 5453 static int 5454 check_time_syntax (struct berval *val, 5455 int start, 5456 int *parts, 5457 struct berval *fraction) 5458 { 5459 /* 5460 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) 5461 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM] 5462 * GeneralizedTime supports leap seconds, UTCTime does not. 5463 */ 5464 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 }; 5465 static const int mdays[2][12] = { 5466 /* non-leap years */ 5467 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 5468 /* leap years */ 5469 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 5470 }; 5471 char *p, *e; 5472 int part, c, c1, c2, tzoffset, leapyear = 0; 5473 5474 p = val->bv_val; 5475 e = p + val->bv_len; 5476 5477 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 5478 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */ 5479 #endif 5480 for (part = start; part < 7 && p < e; part++) { 5481 c1 = *p; 5482 if (!ASCII_DIGIT(c1)) { 5483 break; 5484 } 5485 p++; 5486 if (p == e) { 5487 return LDAP_INVALID_SYNTAX; 5488 } 5489 c = *p++; 5490 if (!ASCII_DIGIT(c)) { 5491 return LDAP_INVALID_SYNTAX; 5492 } 5493 c += c1 * 10 - '0' * 11; 5494 if ((part | 1) == 3) { 5495 --c; 5496 if (c < 0) { 5497 return LDAP_INVALID_SYNTAX; 5498 } 5499 } 5500 if (c >= ceiling[part]) { 5501 if (! (c == 60 && part == 6 && start == 0)) 5502 return LDAP_INVALID_SYNTAX; 5503 } 5504 parts[part] = c; 5505 } 5506 if (part < 5 + start) { 5507 return LDAP_INVALID_SYNTAX; 5508 } 5509 for (; part < 9; part++) { 5510 parts[part] = 0; 5511 } 5512 5513 /* leapyear check for the Gregorian calendar (year>1581) */ 5514 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) { 5515 leapyear = 1; 5516 } 5517 5518 if (parts[3] >= mdays[leapyear][parts[2]]) { 5519 return LDAP_INVALID_SYNTAX; 5520 } 5521 5522 if (start == 0) { 5523 fraction->bv_val = p; 5524 fraction->bv_len = 0; 5525 if (p < e && (*p == '.' || *p == ',')) { 5526 char *end_num; 5527 while (++p < e && ASCII_DIGIT(*p)) { 5528 /* EMTPY */; 5529 } 5530 if (p - fraction->bv_val == 1) { 5531 return LDAP_INVALID_SYNTAX; 5532 } 5533 for (end_num = p; end_num[-1] == '0'; --end_num) { 5534 /* EMPTY */; 5535 } 5536 c = end_num - fraction->bv_val; 5537 if (c != 1) fraction->bv_len = c; 5538 } 5539 } 5540 5541 if (p == e) { 5542 /* no time zone */ 5543 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 5544 } 5545 5546 tzoffset = *p++; 5547 switch (tzoffset) { 5548 default: 5549 return LDAP_INVALID_SYNTAX; 5550 case 'Z': 5551 /* UTC */ 5552 break; 5553 case '+': 5554 case '-': 5555 for (part = 7; part < 9 && p < e; part++) { 5556 c1 = *p; 5557 if (!ASCII_DIGIT(c1)) { 5558 break; 5559 } 5560 p++; 5561 if (p == e) { 5562 return LDAP_INVALID_SYNTAX; 5563 } 5564 c2 = *p++; 5565 if (!ASCII_DIGIT(c2)) { 5566 return LDAP_INVALID_SYNTAX; 5567 } 5568 parts[part] = c1 * 10 + c2 - '0' * 11; 5569 if (parts[part] >= ceiling[part]) { 5570 return LDAP_INVALID_SYNTAX; 5571 } 5572 } 5573 if (part < 8 + start) { 5574 return LDAP_INVALID_SYNTAX; 5575 } 5576 5577 if (tzoffset == '-') { 5578 /* negative offset to UTC, ie west of Greenwich */ 5579 parts[4] += parts[7]; 5580 parts[5] += parts[8]; 5581 /* offset is just hhmm, no seconds */ 5582 for (part = 6; --part >= 0; ) { 5583 if (part != 3) { 5584 c = ceiling[part]; 5585 } else { 5586 c = mdays[leapyear][parts[2]]; 5587 } 5588 if (parts[part] >= c) { 5589 if (part == 0) { 5590 return LDAP_INVALID_SYNTAX; 5591 } 5592 parts[part] -= c; 5593 parts[part - 1]++; 5594 continue; 5595 } else if (part != 5) { 5596 break; 5597 } 5598 } 5599 } else { 5600 /* positive offset to UTC, ie east of Greenwich */ 5601 parts[4] -= parts[7]; 5602 parts[5] -= parts[8]; 5603 for (part = 6; --part >= 0; ) { 5604 if (parts[part] < 0) { 5605 if (part == 0) { 5606 return LDAP_INVALID_SYNTAX; 5607 } 5608 if (part != 3) { 5609 c = ceiling[part]; 5610 } else { 5611 /* make first arg to % non-negative */ 5612 c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; 5613 } 5614 parts[part] += c; 5615 parts[part - 1]--; 5616 continue; 5617 } else if (part != 5) { 5618 break; 5619 } 5620 } 5621 } 5622 } 5623 5624 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; 5625 } 5626 5627 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 5628 5629 #if 0 5630 static int 5631 xutcTimeNormalize( 5632 Syntax *syntax, 5633 struct berval *val, 5634 struct berval *normalized ) 5635 { 5636 int parts[9], rc; 5637 5638 rc = check_time_syntax(val, 1, parts, NULL); 5639 if (rc != LDAP_SUCCESS) { 5640 return rc; 5641 } 5642 5643 normalized->bv_val = ch_malloc( 14 ); 5644 if ( normalized->bv_val == NULL ) { 5645 return LBER_ERROR_MEMORY; 5646 } 5647 5648 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ", 5649 parts[1], parts[2] + 1, parts[3] + 1, 5650 parts[4], parts[5], parts[6] ); 5651 normalized->bv_len = 13; 5652 5653 return LDAP_SUCCESS; 5654 } 5655 #endif /* 0 */ 5656 5657 static int 5658 utcTimeValidate( 5659 Syntax *syntax, 5660 struct berval *in ) 5661 { 5662 int parts[9]; 5663 return check_time_syntax(in, 1, parts, NULL); 5664 } 5665 5666 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ 5667 5668 static int 5669 generalizedTimeValidate( 5670 Syntax *syntax, 5671 struct berval *in ) 5672 { 5673 int parts[9]; 5674 struct berval fraction; 5675 return check_time_syntax(in, 0, parts, &fraction); 5676 } 5677 5678 static int 5679 generalizedTimeNormalize( 5680 slap_mask_t usage, 5681 Syntax *syntax, 5682 MatchingRule *mr, 5683 struct berval *val, 5684 struct berval *normalized, 5685 void *ctx ) 5686 { 5687 int parts[9], rc; 5688 unsigned int len; 5689 struct berval fraction; 5690 5691 rc = check_time_syntax(val, 0, parts, &fraction); 5692 if (rc != LDAP_SUCCESS) { 5693 return rc; 5694 } 5695 5696 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len; 5697 normalized->bv_val = slap_sl_malloc( len + 1, ctx ); 5698 if ( BER_BVISNULL( normalized ) ) { 5699 return LBER_ERROR_MEMORY; 5700 } 5701 5702 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d", 5703 parts[0], parts[1], parts[2] + 1, parts[3] + 1, 5704 parts[4], parts[5], parts[6] ); 5705 if ( !BER_BVISEMPTY( &fraction ) ) { 5706 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1, 5707 fraction.bv_val, fraction.bv_len ); 5708 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.'; 5709 } 5710 strcpy( normalized->bv_val + len-1, "Z" ); 5711 normalized->bv_len = len; 5712 5713 return LDAP_SUCCESS; 5714 } 5715 5716 static int 5717 generalizedTimeOrderingMatch( 5718 int *matchp, 5719 slap_mask_t flags, 5720 Syntax *syntax, 5721 MatchingRule *mr, 5722 struct berval *value, 5723 void *assertedValue ) 5724 { 5725 struct berval *asserted = (struct berval *) assertedValue; 5726 ber_len_t v_len = value->bv_len; 5727 ber_len_t av_len = asserted->bv_len; 5728 5729 /* ignore trailing 'Z' when comparing */ 5730 int match = memcmp( value->bv_val, asserted->bv_val, 5731 (v_len < av_len ? v_len : av_len) - 1 ); 5732 if ( match == 0 ) match = v_len - av_len; 5733 5734 /* If used in extensible match filter, match if value < asserted */ 5735 if ( flags & SLAP_MR_EXT ) 5736 match = (match >= 0); 5737 5738 *matchp = match; 5739 return LDAP_SUCCESS; 5740 } 5741 5742 /* Index generation function: Ordered index */ 5743 int generalizedTimeIndexer( 5744 slap_mask_t use, 5745 slap_mask_t flags, 5746 Syntax *syntax, 5747 MatchingRule *mr, 5748 struct berval *prefix, 5749 BerVarray values, 5750 BerVarray *keysp, 5751 void *ctx ) 5752 { 5753 int i, j; 5754 BerVarray keys; 5755 char tmp[5]; 5756 BerValue bvtmp; /* 40 bit index */ 5757 struct lutil_tm tm; 5758 struct lutil_timet tt; 5759 5760 bvtmp.bv_len = sizeof(tmp); 5761 bvtmp.bv_val = tmp; 5762 for( i=0; values[i].bv_val != NULL; i++ ) { 5763 /* just count them */ 5764 } 5765 5766 /* we should have at least one value at this point */ 5767 assert( i > 0 ); 5768 5769 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx ); 5770 5771 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 5772 for( i=0, j=0; values[i].bv_val != NULL; i++ ) { 5773 assert(values[i].bv_val != NULL && values[i].bv_len >= 10); 5774 /* Use 40 bits of time for key */ 5775 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) { 5776 lutil_tm2time( &tm, &tt ); 5777 tmp[0] = tt.tt_gsec & 0xff; 5778 tmp[4] = tt.tt_sec & 0xff; 5779 tt.tt_sec >>= 8; 5780 tmp[3] = tt.tt_sec & 0xff; 5781 tt.tt_sec >>= 8; 5782 tmp[2] = tt.tt_sec & 0xff; 5783 tt.tt_sec >>= 8; 5784 tmp[1] = tt.tt_sec & 0xff; 5785 5786 ber_dupbv_x(&keys[j++], &bvtmp, ctx ); 5787 } 5788 } 5789 5790 keys[j].bv_val = NULL; 5791 keys[j].bv_len = 0; 5792 5793 *keysp = keys; 5794 5795 return LDAP_SUCCESS; 5796 } 5797 5798 /* Index generation function: Ordered index */ 5799 int generalizedTimeFilter( 5800 slap_mask_t use, 5801 slap_mask_t flags, 5802 Syntax *syntax, 5803 MatchingRule *mr, 5804 struct berval *prefix, 5805 void * assertedValue, 5806 BerVarray *keysp, 5807 void *ctx ) 5808 { 5809 BerVarray keys; 5810 char tmp[5]; 5811 BerValue bvtmp; /* 40 bit index */ 5812 BerValue *value = (BerValue *) assertedValue; 5813 struct lutil_tm tm; 5814 struct lutil_timet tt; 5815 5816 bvtmp.bv_len = sizeof(tmp); 5817 bvtmp.bv_val = tmp; 5818 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ 5819 /* Use 40 bits of time for key */ 5820 if ( value->bv_val && value->bv_len >= 10 && 5821 lutil_parsetime( value->bv_val, &tm ) == 0 ) { 5822 5823 lutil_tm2time( &tm, &tt ); 5824 tmp[0] = tt.tt_gsec & 0xff; 5825 tmp[4] = tt.tt_sec & 0xff; 5826 tt.tt_sec >>= 8; 5827 tmp[3] = tt.tt_sec & 0xff; 5828 tt.tt_sec >>= 8; 5829 tmp[2] = tt.tt_sec & 0xff; 5830 tt.tt_sec >>= 8; 5831 tmp[1] = tt.tt_sec & 0xff; 5832 5833 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); 5834 ber_dupbv_x(keys, &bvtmp, ctx ); 5835 keys[1].bv_val = NULL; 5836 keys[1].bv_len = 0; 5837 } else { 5838 keys = NULL; 5839 } 5840 5841 *keysp = keys; 5842 5843 return LDAP_SUCCESS; 5844 } 5845 5846 static int 5847 deliveryMethodValidate( 5848 Syntax *syntax, 5849 struct berval *val ) 5850 { 5851 #undef LENOF 5852 #define LENOF(s) (sizeof(s)-1) 5853 struct berval tmp = *val; 5854 /* 5855 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod ) 5856 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" / 5857 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone" 5858 */ 5859 again: 5860 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX; 5861 5862 switch( tmp.bv_val[0] ) { 5863 case 'a': 5864 case 'A': 5865 if(( tmp.bv_len >= LENOF("any") ) && 5866 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 )) 5867 { 5868 tmp.bv_len -= LENOF("any"); 5869 tmp.bv_val += LENOF("any"); 5870 break; 5871 } 5872 return LDAP_INVALID_SYNTAX; 5873 5874 case 'm': 5875 case 'M': 5876 if(( tmp.bv_len >= LENOF("mhs") ) && 5877 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 )) 5878 { 5879 tmp.bv_len -= LENOF("mhs"); 5880 tmp.bv_val += LENOF("mhs"); 5881 break; 5882 } 5883 return LDAP_INVALID_SYNTAX; 5884 5885 case 'p': 5886 case 'P': 5887 if(( tmp.bv_len >= LENOF("physical") ) && 5888 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 )) 5889 { 5890 tmp.bv_len -= LENOF("physical"); 5891 tmp.bv_val += LENOF("physical"); 5892 break; 5893 } 5894 return LDAP_INVALID_SYNTAX; 5895 5896 case 't': 5897 case 'T': /* telex or teletex or telephone */ 5898 if(( tmp.bv_len >= LENOF("telex") ) && 5899 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 )) 5900 { 5901 tmp.bv_len -= LENOF("telex"); 5902 tmp.bv_val += LENOF("telex"); 5903 break; 5904 } 5905 if(( tmp.bv_len >= LENOF("teletex") ) && 5906 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 )) 5907 { 5908 tmp.bv_len -= LENOF("teletex"); 5909 tmp.bv_val += LENOF("teletex"); 5910 break; 5911 } 5912 if(( tmp.bv_len >= LENOF("telephone") ) && 5913 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 )) 5914 { 5915 tmp.bv_len -= LENOF("telephone"); 5916 tmp.bv_val += LENOF("telephone"); 5917 break; 5918 } 5919 return LDAP_INVALID_SYNTAX; 5920 5921 case 'g': 5922 case 'G': /* g3fax or g4fax */ 5923 if(( tmp.bv_len >= LENOF("g3fax") ) && ( 5924 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) || 5925 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 ))) 5926 { 5927 tmp.bv_len -= LENOF("g3fax"); 5928 tmp.bv_val += LENOF("g3fax"); 5929 break; 5930 } 5931 return LDAP_INVALID_SYNTAX; 5932 5933 case 'i': 5934 case 'I': 5935 if(( tmp.bv_len >= LENOF("ia5") ) && 5936 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 )) 5937 { 5938 tmp.bv_len -= LENOF("ia5"); 5939 tmp.bv_val += LENOF("ia5"); 5940 break; 5941 } 5942 return LDAP_INVALID_SYNTAX; 5943 5944 case 'v': 5945 case 'V': 5946 if(( tmp.bv_len >= LENOF("videotex") ) && 5947 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 )) 5948 { 5949 tmp.bv_len -= LENOF("videotex"); 5950 tmp.bv_val += LENOF("videotex"); 5951 break; 5952 } 5953 return LDAP_INVALID_SYNTAX; 5954 5955 default: 5956 return LDAP_INVALID_SYNTAX; 5957 } 5958 5959 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS; 5960 5961 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 5962 tmp.bv_len--; 5963 tmp.bv_val++; 5964 } 5965 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) { 5966 tmp.bv_len--; 5967 tmp.bv_val++; 5968 } else { 5969 return LDAP_INVALID_SYNTAX; 5970 } 5971 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { 5972 tmp.bv_len--; 5973 tmp.bv_val++; 5974 } 5975 5976 goto again; 5977 } 5978 5979 static int 5980 nisNetgroupTripleValidate( 5981 Syntax *syntax, 5982 struct berval *val ) 5983 { 5984 char *p, *e; 5985 int commas = 0; 5986 5987 if ( BER_BVISEMPTY( val ) ) { 5988 return LDAP_INVALID_SYNTAX; 5989 } 5990 5991 p = (char *)val->bv_val; 5992 e = p + val->bv_len; 5993 5994 if ( *p != '(' /*')'*/ ) { 5995 return LDAP_INVALID_SYNTAX; 5996 } 5997 5998 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) { 5999 if ( *p == ',' ) { 6000 commas++; 6001 if ( commas > 2 ) { 6002 return LDAP_INVALID_SYNTAX; 6003 } 6004 6005 } else if ( !AD_CHAR( *p ) ) { 6006 return LDAP_INVALID_SYNTAX; 6007 } 6008 } 6009 6010 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) { 6011 return LDAP_INVALID_SYNTAX; 6012 } 6013 6014 p++; 6015 6016 if (p != e) { 6017 return LDAP_INVALID_SYNTAX; 6018 } 6019 6020 return LDAP_SUCCESS; 6021 } 6022 6023 static int 6024 bootParameterValidate( 6025 Syntax *syntax, 6026 struct berval *val ) 6027 { 6028 char *p, *e; 6029 6030 if ( BER_BVISEMPTY( val ) ) { 6031 return LDAP_INVALID_SYNTAX; 6032 } 6033 6034 p = (char *)val->bv_val; 6035 e = p + val->bv_len; 6036 6037 /* key */ 6038 for (; ( 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 /* server */ 6049 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) { 6050 if ( !AD_CHAR( *p ) ) { 6051 return LDAP_INVALID_SYNTAX; 6052 } 6053 } 6054 6055 if ( *p != ':' ) { 6056 return LDAP_INVALID_SYNTAX; 6057 } 6058 6059 /* path */ 6060 for ( p++; p < e; p++ ) { 6061 if ( !SLAP_PRINTABLE( *p ) ) { 6062 return LDAP_INVALID_SYNTAX; 6063 } 6064 } 6065 6066 return LDAP_SUCCESS; 6067 } 6068 6069 static int 6070 firstComponentNormalize( 6071 slap_mask_t usage, 6072 Syntax *syntax, 6073 MatchingRule *mr, 6074 struct berval *val, 6075 struct berval *normalized, 6076 void *ctx ) 6077 { 6078 int rc; 6079 struct berval comp; 6080 ber_len_t len; 6081 6082 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) { 6083 ber_dupbv_x( normalized, val, ctx ); 6084 return LDAP_SUCCESS; 6085 } 6086 6087 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; 6088 6089 if( ! ( val->bv_val[0] == '(' /*')'*/ 6090 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' ) 6091 && ! ( val->bv_val[0] == '{' /*'}'*/ 6092 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) ) 6093 { 6094 return LDAP_INVALID_SYNTAX; 6095 } 6096 6097 /* trim leading white space */ 6098 for( len=1; 6099 len < val->bv_len && ASCII_SPACE(val->bv_val[len]); 6100 len++ ) 6101 { 6102 /* empty */ 6103 } 6104 6105 /* grab next word */ 6106 comp.bv_val = &val->bv_val[len]; 6107 len = val->bv_len - len - STRLENOF(/*"{"*/ "}"); 6108 for( comp.bv_len = 0; 6109 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len; 6110 comp.bv_len++ ) 6111 { 6112 /* empty */ 6113 } 6114 6115 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) { 6116 rc = numericoidValidate( NULL, &comp ); 6117 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) { 6118 rc = integerValidate( NULL, &comp ); 6119 } else { 6120 rc = LDAP_INVALID_SYNTAX; 6121 } 6122 6123 6124 if( rc == LDAP_SUCCESS ) { 6125 ber_dupbv_x( normalized, &comp, ctx ); 6126 } 6127 6128 return rc; 6129 } 6130 6131 static char *country_gen_syn[] = { 6132 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */ 6133 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */ 6134 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */ 6135 NULL 6136 }; 6137 6138 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " 6139 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " 6140 6141 static slap_syntax_defs_rec syntax_defs[] = { 6142 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " 6143 X_BINARY X_NOT_H_R ")", 6144 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL}, 6145 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")", 6146 0, NULL, NULL, NULL}, 6147 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", 6148 0, NULL, NULL, NULL}, 6149 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " 6150 X_NOT_H_R ")", 6151 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 6152 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " 6153 X_NOT_H_R ")", 6154 SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 6155 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", 6156 0, NULL, bitStringValidate, NULL }, 6157 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", 6158 0, NULL, booleanValidate, NULL}, 6159 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " 6160 X_BINARY X_NOT_H_R ")", 6161 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6162 NULL, certificateValidate, NULL}, 6163 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " 6164 X_BINARY X_NOT_H_R ")", 6165 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6166 NULL, certificateListValidate, NULL}, 6167 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " 6168 X_BINARY X_NOT_H_R ")", 6169 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6170 NULL, sequenceValidate, NULL}, 6171 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' " 6172 X_BINARY X_NOT_H_R ")", 6173 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, 6174 NULL, attributeCertificateValidate, NULL}, 6175 #if 0 /* need to go __after__ printableString */ 6176 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 6177 0, "1.3.6.1.4.1.1466.115.121.1.44", 6178 countryStringValidate, NULL}, 6179 #endif 6180 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", 6181 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty}, 6182 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )", 6183 0, NULL, rdnValidate, rdnPretty}, 6184 #ifdef LDAP_COMP_MATCH 6185 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", 6186 0, NULL, allComponentsValidate, NULL}, 6187 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ", 6188 0, NULL, componentFilterValidate, NULL}, 6189 #endif 6190 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )", 6191 0, NULL, NULL, NULL}, 6192 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", 6193 0, NULL, deliveryMethodValidate, NULL}, 6194 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", 6195 0, NULL, UTF8StringValidate, NULL}, 6196 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", 6197 0, NULL, NULL, NULL}, 6198 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", 6199 0, NULL, NULL, NULL}, 6200 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )", 6201 0, NULL, NULL, NULL}, 6202 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )", 6203 0, NULL, NULL, NULL}, 6204 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", 6205 0, NULL, NULL, NULL}, 6206 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", 6207 0, NULL, printablesStringValidate, NULL}, 6208 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")", 6209 SLAP_SYNTAX_BLOB, NULL, NULL, NULL}, 6210 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", 6211 0, NULL, generalizedTimeValidate, NULL}, 6212 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", 6213 0, NULL, NULL, NULL}, 6214 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", 6215 0, NULL, IA5StringValidate, NULL}, 6216 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", 6217 0, NULL, integerValidate, NULL}, 6218 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")", 6219 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL}, 6220 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )", 6221 0, NULL, NULL, NULL}, 6222 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", 6223 0, NULL, NULL, NULL}, 6224 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", 6225 0, NULL, NULL, NULL}, 6226 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", 6227 0, NULL, NULL, NULL}, 6228 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", 6229 0, NULL, NULL, NULL}, 6230 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", 6231 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty }, 6232 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", 6233 0, NULL, NULL, NULL}, 6234 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", 6235 0, NULL, numericStringValidate, NULL}, 6236 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", 6237 0, NULL, NULL, NULL}, 6238 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", 6239 0, NULL, numericoidValidate, NULL}, 6240 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", 6241 0, NULL, IA5StringValidate, NULL}, 6242 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", 6243 0, NULL, blobValidate, NULL}, 6244 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", 6245 0, NULL, postalAddressValidate, NULL}, 6246 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", 6247 0, NULL, NULL, NULL}, 6248 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", 6249 0, NULL, NULL, NULL}, 6250 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", 6251 0, NULL, printableStringValidate, NULL}, 6252 /* moved here because now depends on Directory String, IA5 String 6253 * and Printable String */ 6254 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 6255 0, country_gen_syn, countryStringValidate, NULL}, 6256 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )", 6257 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */ 6258 0, NULL, subtreeSpecificationValidate, NULL}, 6259 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' " 6260 X_BINARY X_NOT_H_R ")", 6261 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL}, 6262 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", 6263 0, NULL, printableStringValidate, NULL}, 6264 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", 6265 0, NULL, NULL, NULL}, 6266 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", 6267 0, NULL, printablesStringValidate, NULL}, 6268 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX 6269 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", 6270 0, NULL, utcTimeValidate, NULL}, 6271 #endif 6272 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", 6273 0, NULL, NULL, NULL}, 6274 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )", 6275 0, NULL, NULL, NULL}, 6276 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )", 6277 0, NULL, NULL, NULL}, 6278 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )", 6279 0, NULL, NULL, NULL}, 6280 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", 6281 0, NULL, NULL, NULL}, 6282 6283 /* RFC 2307 NIS Syntaxes */ 6284 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )", 6285 0, NULL, nisNetgroupTripleValidate, NULL}, 6286 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", 6287 0, NULL, bootParameterValidate, NULL}, 6288 6289 /* draft-zeilenga-ldap-x509 */ 6290 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )", 6291 SLAP_SYNTAX_HIDE, NULL, 6292 serialNumberAndIssuerValidate, 6293 serialNumberAndIssuerPretty}, 6294 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )", 6295 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6296 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )", 6297 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6298 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )", 6299 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6300 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )", 6301 SLAP_SYNTAX_HIDE, NULL, 6302 issuerAndThisUpdateValidate, 6303 issuerAndThisUpdatePretty}, 6304 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )", 6305 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6306 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )", 6307 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6308 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )", 6309 SLAP_SYNTAX_HIDE, NULL, 6310 serialNumberAndIssuerSerialValidate, 6311 serialNumberAndIssuerSerialPretty}, 6312 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )", 6313 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6314 6315 #ifdef SLAPD_AUTHPASSWD 6316 /* needs updating */ 6317 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )", 6318 SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, 6319 #endif 6320 6321 {"( 1.3.6.1.1.16.1 DESC 'UUID' )", 6322 0, NULL, UUIDValidate, UUIDPretty}, 6323 6324 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )", 6325 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty }, 6326 6327 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )", 6328 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty }, 6329 6330 /* OpenLDAP Void Syntax */ 6331 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , 6332 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL}, 6333 6334 /* FIXME: OID is unused, but not registered yet */ 6335 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )", 6336 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty}, 6337 6338 {NULL, 0, NULL, NULL, NULL} 6339 }; 6340 6341 char *csnSIDMatchSyntaxes[] = { 6342 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */, 6343 NULL 6344 }; 6345 char *certificateExactMatchSyntaxes[] = { 6346 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 6347 NULL 6348 }; 6349 char *certificateListExactMatchSyntaxes[] = { 6350 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */, 6351 NULL 6352 }; 6353 char *attributeCertificateExactMatchSyntaxes[] = { 6354 attributeCertificateSyntaxOID /* attributeCertificate */, 6355 NULL 6356 }; 6357 6358 #ifdef LDAP_COMP_MATCH 6359 char *componentFilterMatchSyntaxes[] = { 6360 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, 6361 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */, 6362 attributeCertificateSyntaxOID /* attributeCertificate */, 6363 NULL 6364 }; 6365 #endif 6366 6367 char *directoryStringSyntaxes[] = { 6368 "1.3.6.1.4.1.1466.115.121.1.11" /* countryString */, 6369 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */, 6370 "1.3.6.1.4.1.1466.115.121.1.50" /* telephoneNumber */, 6371 NULL 6372 }; 6373 char *integerFirstComponentMatchSyntaxes[] = { 6374 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */, 6375 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */, 6376 NULL 6377 }; 6378 char *objectIdentifierFirstComponentMatchSyntaxes[] = { 6379 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */, 6380 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */, 6381 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */, 6382 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */, 6383 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */, 6384 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */, 6385 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */, 6386 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */, 6387 NULL 6388 }; 6389 6390 /* 6391 * Other matching rules in X.520 that we do not use (yet): 6392 * 6393 * 2.5.13.25 uTCTimeMatch 6394 * 2.5.13.26 uTCTimeOrderingMatch 6395 * 2.5.13.31* directoryStringFirstComponentMatch 6396 * 2.5.13.32* wordMatch 6397 * 2.5.13.33* keywordMatch 6398 * 2.5.13.36+ certificatePairExactMatch 6399 * 2.5.13.37+ certificatePairMatch 6400 * 2.5.13.40+ algorithmIdentifierMatch 6401 * 2.5.13.41* storedPrefixMatch 6402 * 2.5.13.42 attributeCertificateMatch 6403 * 2.5.13.43 readerAndKeyIDMatch 6404 * 2.5.13.44 attributeIntegrityMatch 6405 * 6406 * (*) described in RFC 3698 (LDAP: Additional Matching Rules) 6407 * (+) described in draft-zeilenga-ldap-x509 6408 */ 6409 static slap_mrule_defs_rec mrule_defs[] = { 6410 /* 6411 * EQUALITY matching rules must be listed after associated APPROX 6412 * matching rules. So, we list all APPROX matching rules first. 6413 */ 6414 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' " 6415 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6416 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 6417 NULL, NULL, directoryStringApproxMatch, 6418 directoryStringApproxIndexer, directoryStringApproxFilter, 6419 NULL}, 6420 6421 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' " 6422 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6423 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, 6424 NULL, NULL, IA5StringApproxMatch, 6425 IA5StringApproxIndexer, IA5StringApproxFilter, 6426 NULL}, 6427 6428 /* 6429 * Other matching rules 6430 */ 6431 6432 {"( 2.5.13.0 NAME 'objectIdentifierMatch' " 6433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", 6434 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6435 NULL, NULL, octetStringMatch, 6436 octetStringIndexer, octetStringFilter, 6437 NULL }, 6438 6439 {"( 2.5.13.1 NAME 'distinguishedNameMatch' " 6440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6441 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6442 NULL, dnNormalize, dnMatch, 6443 octetStringIndexer, octetStringFilter, 6444 NULL }, 6445 6446 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' " 6447 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6448 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6449 NULL, dnNormalize, dnRelativeMatch, 6450 NULL, NULL, 6451 NULL }, 6452 6453 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' " 6454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6455 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6456 NULL, dnNormalize, dnRelativeMatch, 6457 NULL, NULL, 6458 NULL }, 6459 6460 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' " 6461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6462 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6463 NULL, dnNormalize, dnRelativeMatch, 6464 NULL, NULL, 6465 NULL }, 6466 6467 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' " 6468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", 6469 SLAP_MR_HIDE | SLAP_MR_EXT, NULL, 6470 NULL, dnNormalize, dnRelativeMatch, 6471 NULL, NULL, 6472 NULL }, 6473 6474 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' " 6475 "SYNTAX 1.2.36.79672281.1.5.0 )", 6476 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6477 NULL, rdnNormalize, rdnMatch, 6478 octetStringIndexer, octetStringFilter, 6479 NULL }, 6480 6481 #ifdef LDAP_COMP_MATCH 6482 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' " 6483 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */ 6484 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes, 6485 NULL, NULL , componentFilterMatch, 6486 octetStringIndexer, octetStringFilter, 6487 NULL }, 6488 6489 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' " 6490 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */ 6491 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 6492 NULL, NULL , allComponentsMatch, 6493 octetStringIndexer, octetStringFilter, 6494 NULL }, 6495 6496 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' " 6497 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */ 6498 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL, 6499 NULL, NULL , directoryComponentsMatch, 6500 octetStringIndexer, octetStringFilter, 6501 NULL }, 6502 #endif 6503 6504 {"( 2.5.13.2 NAME 'caseIgnoreMatch' " 6505 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6506 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 6507 NULL, UTF8StringNormalize, octetStringMatch, 6508 octetStringIndexer, octetStringFilter, 6509 directoryStringApproxMatchOID }, 6510 6511 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' " 6512 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6513 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes, 6514 NULL, UTF8StringNormalize, octetStringOrderingMatch, 6515 NULL, NULL, 6516 "caseIgnoreMatch" }, 6517 6518 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " 6519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */ 6520 SLAP_MR_SUBSTR, directoryStringSyntaxes, 6521 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 6522 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6523 "caseIgnoreMatch" }, 6524 6525 {"( 2.5.13.5 NAME 'caseExactMatch' " 6526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6527 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes, 6528 NULL, UTF8StringNormalize, octetStringMatch, 6529 octetStringIndexer, octetStringFilter, 6530 directoryStringApproxMatchOID }, 6531 6532 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' " 6533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 6534 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes, 6535 NULL, UTF8StringNormalize, octetStringOrderingMatch, 6536 NULL, NULL, 6537 "caseExactMatch" }, 6538 6539 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " 6540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */ 6541 SLAP_MR_SUBSTR, directoryStringSyntaxes, 6542 NULL, UTF8StringNormalize, directoryStringSubstringsMatch, 6543 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6544 "caseExactMatch" }, 6545 6546 {"( 2.5.13.8 NAME 'numericStringMatch' " 6547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 6548 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6549 NULL, numericStringNormalize, octetStringMatch, 6550 octetStringIndexer, octetStringFilter, 6551 NULL }, 6552 6553 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' " 6554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", 6555 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL, 6556 NULL, numericStringNormalize, octetStringOrderingMatch, 6557 NULL, NULL, 6558 "numericStringMatch" }, 6559 6560 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' " 6561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */ 6562 SLAP_MR_SUBSTR, NULL, 6563 NULL, numericStringNormalize, octetStringSubstringsMatch, 6564 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6565 "numericStringMatch" }, 6566 6567 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' " 6568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */ 6569 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6570 NULL, postalAddressNormalize, octetStringMatch, 6571 octetStringIndexer, octetStringFilter, 6572 NULL }, 6573 6574 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' " 6575 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */ 6576 SLAP_MR_SUBSTR, NULL, 6577 NULL, NULL, NULL, NULL, NULL, 6578 "caseIgnoreListMatch" }, 6579 6580 {"( 2.5.13.13 NAME 'booleanMatch' " 6581 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )", 6582 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6583 NULL, NULL, booleanMatch, 6584 octetStringIndexer, octetStringFilter, 6585 NULL }, 6586 6587 {"( 2.5.13.14 NAME 'integerMatch' " 6588 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6589 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6590 NULL, NULL, integerMatch, 6591 integerIndexer, integerFilter, 6592 NULL }, 6593 6594 {"( 2.5.13.15 NAME 'integerOrderingMatch' " 6595 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", 6596 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6597 NULL, NULL, integerMatch, 6598 NULL, NULL, 6599 "integerMatch" }, 6600 6601 {"( 2.5.13.16 NAME 'bitStringMatch' " 6602 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", 6603 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6604 NULL, NULL, octetStringMatch, 6605 octetStringIndexer, octetStringFilter, 6606 NULL }, 6607 6608 {"( 2.5.13.17 NAME 'octetStringMatch' " 6609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6610 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6611 NULL, NULL, octetStringMatch, 6612 octetStringIndexer, octetStringFilter, 6613 NULL }, 6614 6615 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' " 6616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6617 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL, 6618 NULL, NULL, octetStringOrderingMatch, 6619 NULL, NULL, 6620 "octetStringMatch" }, 6621 6622 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' " 6623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", 6624 SLAP_MR_SUBSTR, NULL, 6625 NULL, NULL, octetStringSubstringsMatch, 6626 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6627 "octetStringMatch" }, 6628 6629 {"( 2.5.13.20 NAME 'telephoneNumberMatch' " 6630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", 6631 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6632 NULL, 6633 telephoneNumberNormalize, octetStringMatch, 6634 octetStringIndexer, octetStringFilter, 6635 NULL }, 6636 6637 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' " 6638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */ 6639 SLAP_MR_SUBSTR, NULL, 6640 NULL, telephoneNumberNormalize, octetStringSubstringsMatch, 6641 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6642 "telephoneNumberMatch" }, 6643 6644 {"( 2.5.13.22 NAME 'presentationAddressMatch' " 6645 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", 6646 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6647 NULL, NULL, NULL, NULL, NULL, NULL }, 6648 6649 {"( 2.5.13.23 NAME 'uniqueMemberMatch' " 6650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */ 6651 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6652 NULL, uniqueMemberNormalize, uniqueMemberMatch, 6653 uniqueMemberIndexer, uniqueMemberFilter, 6654 NULL }, 6655 6656 {"( 2.5.13.24 NAME 'protocolInformationMatch' " 6657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", 6658 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6659 NULL, NULL, NULL, NULL, NULL, NULL }, 6660 6661 {"( 2.5.13.27 NAME 'generalizedTimeMatch' " 6662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 6663 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6664 NULL, generalizedTimeNormalize, octetStringMatch, 6665 generalizedTimeIndexer, generalizedTimeFilter, 6666 NULL }, 6667 6668 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " 6669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", 6670 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6671 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch, 6672 NULL, NULL, 6673 "generalizedTimeMatch" }, 6674 6675 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' " 6676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */ 6677 SLAP_MR_EQUALITY | SLAP_MR_EXT, 6678 integerFirstComponentMatchSyntaxes, 6679 NULL, firstComponentNormalize, integerMatch, 6680 octetStringIndexer, octetStringFilter, 6681 NULL }, 6682 6683 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' " 6684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */ 6685 SLAP_MR_EQUALITY | SLAP_MR_EXT, 6686 objectIdentifierFirstComponentMatchSyntaxes, 6687 NULL, firstComponentNormalize, octetStringMatch, 6688 octetStringIndexer, octetStringFilter, 6689 NULL }, 6690 6691 {"( 2.5.13.34 NAME 'certificateExactMatch' " 6692 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */ 6693 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, 6694 NULL, certificateExactNormalize, octetStringMatch, 6695 octetStringIndexer, octetStringFilter, 6696 NULL }, 6697 6698 {"( 2.5.13.35 NAME 'certificateMatch' " 6699 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */ 6700 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6701 NULL, NULL, NULL, NULL, NULL, 6702 NULL }, 6703 6704 {"( 2.5.13.38 NAME 'certificateListExactMatch' " 6705 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */ 6706 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes, 6707 NULL, certificateListExactNormalize, octetStringMatch, 6708 octetStringIndexer, octetStringFilter, 6709 NULL }, 6710 6711 {"( 2.5.13.39 NAME 'certificateListMatch' " 6712 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */ 6713 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6714 NULL, NULL, NULL, NULL, NULL, 6715 NULL }, 6716 6717 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' " 6718 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )", 6719 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes, 6720 NULL, attributeCertificateExactNormalize, octetStringMatch, 6721 octetStringIndexer, octetStringFilter, 6722 NULL }, 6723 6724 {"( 2.5.13.46 NAME 'attributeCertificateMatch' " 6725 "SYNTAX " attributeCertificateAssertionSyntaxOID " )", 6726 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL, 6727 NULL, NULL, NULL, NULL, NULL, 6728 NULL }, 6729 6730 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " 6731 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6732 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6733 NULL, IA5StringNormalize, octetStringMatch, 6734 octetStringIndexer, octetStringFilter, 6735 IA5StringApproxMatchOID }, 6736 6737 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' " 6738 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6739 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, 6740 NULL, IA5StringNormalize, octetStringMatch, 6741 octetStringIndexer, octetStringFilter, 6742 IA5StringApproxMatchOID }, 6743 6744 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' " 6745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6746 SLAP_MR_SUBSTR, NULL, 6747 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 6748 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6749 "caseIgnoreIA5Match" }, 6750 6751 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' " 6752 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", 6753 SLAP_MR_SUBSTR, NULL, 6754 NULL, IA5StringNormalize, directoryStringSubstringsMatch, 6755 octetStringSubstringsIndexer, octetStringSubstringsFilter, 6756 "caseExactIA5Match" }, 6757 6758 #ifdef SLAPD_AUTHPASSWD 6759 /* needs updating */ 6760 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' " 6761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */ 6762 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 6763 NULL, NULL, authPasswordMatch, 6764 NULL, NULL, 6765 NULL}, 6766 #endif 6767 6768 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' " 6769 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */ 6770 SLAP_MR_EXT, NULL, 6771 NULL, NULL, integerBitAndMatch, 6772 NULL, NULL, 6773 "integerMatch" }, 6774 6775 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' " 6776 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */ 6777 SLAP_MR_EXT, NULL, 6778 NULL, NULL, integerBitOrMatch, 6779 NULL, NULL, 6780 "integerMatch" }, 6781 6782 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' " 6783 "SYNTAX 1.3.6.1.1.16.1 )", 6784 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL, 6785 NULL, UUIDNormalize, octetStringMatch, 6786 octetStringIndexer, octetStringFilter, 6787 NULL}, 6788 6789 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' " 6790 "SYNTAX 1.3.6.1.1.16.1 )", 6791 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL, 6792 NULL, UUIDNormalize, octetStringOrderingMatch, 6793 octetStringIndexer, octetStringFilter, 6794 "UUIDMatch"}, 6795 6796 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' " 6797 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 6798 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL, 6799 NULL, csnNormalize, csnMatch, 6800 csnIndexer, csnFilter, 6801 NULL}, 6802 6803 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' " 6804 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )", 6805 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, 6806 NULL, csnNormalize, csnOrderingMatch, 6807 NULL, NULL, 6808 "CSNMatch" }, 6809 6810 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' " 6811 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )", 6812 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes, 6813 NULL, csnSidNormalize, octetStringMatch, 6814 octetStringIndexer, octetStringFilter, 6815 NULL }, 6816 6817 /* FIXME: OID is unused, but not registered yet */ 6818 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' " 6819 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */ 6820 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, 6821 NULL, authzNormalize, authzMatch, 6822 NULL, NULL, 6823 NULL}, 6824 6825 {NULL, SLAP_MR_NONE, NULL, 6826 NULL, NULL, NULL, NULL, NULL, 6827 NULL } 6828 }; 6829 6830 int 6831 slap_schema_init( void ) 6832 { 6833 int res; 6834 int i; 6835 6836 /* we should only be called once (from main) */ 6837 assert( schema_init_done == 0 ); 6838 6839 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { 6840 res = register_syntax( &syntax_defs[i] ); 6841 6842 if ( res ) { 6843 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n", 6844 syntax_defs[i].sd_desc ); 6845 return LDAP_OTHER; 6846 } 6847 } 6848 6849 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) { 6850 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE && 6851 mrule_defs[i].mrd_compat_syntaxes == NULL ) 6852 { 6853 fprintf( stderr, 6854 "slap_schema_init: Ignoring unusable matching rule %s\n", 6855 mrule_defs[i].mrd_desc ); 6856 continue; 6857 } 6858 6859 res = register_matching_rule( &mrule_defs[i] ); 6860 6861 if ( res ) { 6862 fprintf( stderr, 6863 "slap_schema_init: Error registering matching rule %s\n", 6864 mrule_defs[i].mrd_desc ); 6865 return LDAP_OTHER; 6866 } 6867 } 6868 6869 res = slap_schema_load(); 6870 schema_init_done = 1; 6871 return res; 6872 } 6873 6874 void 6875 schema_destroy( void ) 6876 { 6877 oidm_destroy(); 6878 oc_destroy(); 6879 at_destroy(); 6880 mr_destroy(); 6881 mru_destroy(); 6882 syn_destroy(); 6883 6884 if( schema_init_done ) { 6885 ldap_pvt_thread_mutex_destroy( &ad_index_mutex ); 6886 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex ); 6887 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex ); 6888 } 6889 } 6890