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