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