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