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