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