Syntax *syntax,
struct berval *in );
+#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
+static int
+utcTimeValidate(
+ Syntax *syntax,
+ struct berval *in );
+#endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
+
static int
inValidate(
Syntax *syntax,
SLAP_X509_V3 = 2
};
+enum {
+ SLAP_TAG_UTCTIME = 0x17U,
+ SLAP_TAG_GENERALIZEDTIME = 0x18U
+};
+
+
#define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
enum {
};
/* X.509 certificate validation */
-static int certificateValidate( Syntax *syntax, struct berval *in )
+static int
+certificateValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
}
/* X.509 certificate list validation */
-static int certificateListValidate( Syntax *syntax, struct berval *in )
+static int
+certificateListValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len ); /* thisUpdate */
/* Time is a CHOICE { UTCTime, GeneralizedTime } */
- if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
+ if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
/* Optional nextUpdate */
tag = ber_skip_tag( ber, &len );
- if ( tag == 0x17U || tag == 0x18U ) {
+ if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
}
/* RFC 4517 Section 3.3.2 Bit String:
- * BitString = SQUOTE *binary-digit SQUOTE "B"
- * binary-digit = "0" / "1"
+ * BitString = SQUOTE *binary-digit SQUOTE "B"
+ * binary-digit = "0" / "1"
*
* where SQUOTE [RFC4512] is
* SQUOTE = %x27 ; single quote ("'")
}
/* Work through the asserted value's words, to see if at least some
- of the words are there, in the same order. */
+ * of the words are there, in the same order. */
len = 0;
while ( (ber_len_t) nextchunk < assertv->bv_len ) {
len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
return LDAP_SUCCESS;
}
+static int
+postalAddressValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ struct berval bv = *in;
+ int c;
+
+ for ( c = 0; c < in->bv_len; c++ ) {
+ if ( in->bv_val[c] == '\\' ) {
+ c++;
+ if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
+ && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
+ {
+ return LDAP_INVALID_SYNTAX;
+ }
+ continue;
+ }
+
+ if ( in->bv_val[c] == '$' ) {
+ bv.bv_len = &in->bv_val[c] - bv.bv_val;
+ if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ bv.bv_val = &in->bv_val[c] + 1;
+ }
+ }
+
+ bv.bv_len = &in->bv_val[c] - bv.bv_val;
+ return UTF8StringValidate( NULL, &bv );
+}
+
+static int
+postalAddressNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ BerVarray lines = NULL, nlines = NULL;
+ int l, c;
+ int rc = LDAP_SUCCESS;
+ MatchingRule *xmr = NULL;
+ char *p;
+
+ if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
+ xmr = slap_schema.si_mr_caseIgnoreMatch;
+
+ } else {
+ xmr = slap_schema.si_mr_caseExactMatch;
+ }
+
+ for ( l = 0, c = 0; c < val->bv_len; c++ ) {
+ if ( val->bv_val[c] == '$' ) {
+ l++;
+ }
+ }
+
+ lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
+ nlines = &lines[l + 2];
+
+ lines[0].bv_val = val->bv_val;
+ for ( l = 0, c = 0; c < val->bv_len; c++ ) {
+ if ( val->bv_val[c] == '$' ) {
+ lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
+ l++;
+ lines[l].bv_val = &val->bv_val[c + 1];
+ }
+ }
+ lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
+
+ normalized->bv_len = l;
+
+ for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
+ /* NOTE: we directly normalize each line,
+ * without unescaping the values, since the special
+ * values '\24' ('$') and '\5C' ('\') are not affected
+ * by normalization */
+ rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
+ if ( rc != LDAP_SUCCESS ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+ normalized->bv_len += nlines[l].bv_len;
+ }
+
+ normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
+
+ p = normalized->bv_val;
+ for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
+ p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
+
+ *p++ = '$';
+ }
+ *--p = '\0';
+
+ assert( p - normalized->bv_val == normalized->bv_len );
+
+done:;
+ if ( nlines != NULL ) {
+ for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
+ slap_sl_free( nlines[l].bv_val, ctx );
+ }
+
+ slap_sl_free( lines, ctx );
+ }
+
+ return rc;
+}
+
int
numericoidValidate(
Syntax *syntax,
}
rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
if ( rc )
- goto leave;
+ goto func_leave;
}
*keysp = keys;
-leave:
+func_leave:
if ( itmp.bv_val != ibuf ) {
slap_sl_free( itmp.bv_val, ctx );
}
keys[0].bv_len = index_intlen;
keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
+ keys[1].bv_len = 0;
+ keys[1].bv_val = NULL;
iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
return LDAP_SUCCESS;
}
+static int
+checkNum( struct berval *in, struct berval *out )
+{
+ /* parse serialNumber */
+ int neg = 0;
+ char first = '\0';
+ int extra = 0;
+
+ out->bv_val = in->bv_val;
+ out->bv_len = 0;
+
+ if ( out->bv_val[0] == '-' ) {
+ neg++;
+ out->bv_len++;
+ }
+
+ if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
+ first = out->bv_val[2];
+ extra = 2;
+
+ out->bv_len += STRLENOF("0x");
+ for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
+ if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
+ }
+
+ } else if ( out->bv_val[0] == '\'' ) {
+ first = out->bv_val[1];
+ extra = 3;
+
+ out->bv_len += STRLENOF("'");
+
+ for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
+ if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
+ }
+ if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
+ return -1;
+ }
+ out->bv_len += STRLENOF("'H");
+
+ } else {
+ first = out->bv_val[0];
+ for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
+ if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
+ }
+ }
+
+ if ( !( out->bv_len > neg ) ) {
+ return -1;
+ }
+
+ if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
+ return -1;
+ }
+
+ return 0;
+}
+
static int
serialNumberAndIssuerCheck(
struct berval *in,
struct berval *sn,
struct berval *is,
- void *ctx
-)
+ void *ctx )
{
- int is_hex = 0, n;
+ int n;
if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
} else {
/* Parse GSER format */
- int havesn=0,haveissuer=0;
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_ISSUER = 0x1,
+ HAVE_SN = 0x2,
+ HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
+ } have = HAVE_NONE;
+
+ int numdquotes = 0;
struct berval x = *in;
struct berval ni;
x.bv_val++;
- x.bv_len-=2;
-
- /* eat leading spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
- /* empty */;
- }
-
- if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
- return LDAP_INVALID_SYNTAX;
- }
-
- /* should be at issuer or serialNumber NamedValue */
- if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
- /* parse issuer */
- x.bv_val += STRLENOF("issuer");
- x.bv_len -= STRLENOF("issuer");
-
- if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
+ x.bv_len -= 2;
+ do {
/* eat leading spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
/* empty */;
}
- /* For backward compatibility, this part is optional */
- if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
- x.bv_val += STRLENOF("rdnSequence:");
- x.bv_len -= STRLENOF("rdnSequence:");
- }
+ /* should be at issuer or serialNumber NamedValue */
+ if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
+ if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
- if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
+ /* parse issuer */
+ x.bv_val += STRLENOF("issuer");
+ x.bv_len -= STRLENOF("issuer");
- is->bv_val = x.bv_val;
- is->bv_len = 0;
+ if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
- for( ; is->bv_len < x.bv_len; ) {
- if ( is->bv_val[is->bv_len] != '"' ) {
- is->bv_len++;
- continue;
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
}
- if ( is->bv_val[is->bv_len+1] == '"' ) {
- /* double dquote */
- is->bv_len+=2;
- continue;
+
+ /* For backward compatibility, this part is optional */
+ if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
+ x.bv_val += STRLENOF("rdnSequence:");
+ x.bv_len -= STRLENOF("rdnSequence:");
}
- break;
- }
- x.bv_val += is->bv_len+1;
- x.bv_len -= is->bv_len+1;
- if ( x.bv_len < STRLENOF(",serialNumber 0")) {
- return LDAP_INVALID_SYNTAX;
- }
+ if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
- haveissuer++;
+ is->bv_val = x.bv_val;
+ is->bv_len = 0;
- } else if( strncasecmp( x.bv_val, "serialNumber",
- STRLENOF("serialNumber")) == 0 )
- {
- /* parse serialNumber */
- int neg=0;
- x.bv_val += STRLENOF("serialNumber");
- x.bv_len -= STRLENOF("serialNumber");
+ for ( ; is->bv_len < x.bv_len; ) {
+ if ( is->bv_val[is->bv_len] != '"' ) {
+ is->bv_len++;
+ continue;
+ }
+ if ( is->bv_val[is->bv_len+1] == '"' ) {
+ /* double dquote */
+ is->bv_len += 2;
+ continue;
+ }
+ break;
+ }
+ x.bv_val += is->bv_len + 1;
+ x.bv_len -= is->bv_len + 1;
- if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
+ have |= HAVE_ISSUER;
- /* eat leading spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
- /* empty */;
- }
-
- sn->bv_val = x.bv_val;
- sn->bv_len = 0;
+ } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
+ {
+ if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
- if( sn->bv_val[0] == '-' ) {
- neg++;
- sn->bv_len++;
- }
+ /* parse serialNumber */
+ x.bv_val += STRLENOF("serialNumber");
+ x.bv_len -= STRLENOF("serialNumber");
- if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
- sn->bv_val[1] == 'X' )) {
- is_hex = 1;
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
- }
- } else if ( sn->bv_val[0] == '\'' ) {
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+ if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
+
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
}
- if ( sn->bv_val[sn->bv_len] == '\'' &&
- sn->bv_val[sn->bv_len+1] == 'H' )
- is_hex = 1;
- else
+
+ if ( checkNum( &x, sn ) ) {
return LDAP_INVALID_SYNTAX;
- sn->bv_len += 2;
- } else {
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
}
- }
- if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
- if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
- return LDAP_INVALID_SYNTAX;
- }
+ x.bv_val += sn->bv_len;
+ x.bv_len -= sn->bv_len;
- x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
+ have |= HAVE_SN;
- if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
+ } else {
return LDAP_INVALID_SYNTAX;
}
- havesn++;
-
- } else return LDAP_INVALID_SYNTAX;
-
- if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
-
- /* eat spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
- /* empty */;
- }
-
- /* should be at remaining NamedValue */
- if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
- STRLENOF("issuer" )) == 0 ))
- {
- /* parse issuer */
- x.bv_val += STRLENOF("issuer");
- x.bv_len -= STRLENOF("issuer");
-
- if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
-
/* eat leading spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
- /* empty */;
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
}
- /* For backward compatibility, this part is optional */
- if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
- x.bv_val += STRLENOF("rdnSequence:");
- x.bv_len -= STRLENOF("rdnSequence:");
+ if ( have == HAVE_ALL ) {
+ break;
}
- if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
-
- is->bv_val = x.bv_val;
- is->bv_len = 0;
-
- for( ; is->bv_len < x.bv_len; ) {
- if ( is->bv_val[is->bv_len] != '"' ) {
- is->bv_len++;
- continue;
- }
- if ( is->bv_val[is->bv_len+1] == '"' ) {
- /* double dquote */
- is->bv_len+=2;
- continue;
- }
- break;
+ if ( x.bv_val[0] != ',' ) {
+ return LDAP_INVALID_SYNTAX;
}
- x.bv_val += is->bv_len+1;
- x.bv_len -= is->bv_len+1;
- } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
- STRLENOF("serialNumber")) == 0 ))
- {
- /* parse serialNumber */
- int neg=0;
- x.bv_val += STRLENOF("serialNumber");
- x.bv_len -= STRLENOF("serialNumber");
+ x.bv_val++;
+ x.bv_len--;
+ } while ( 1 );
- if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
- x.bv_val++; x.bv_len--;
+ /* should have no characters left... */
+ if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
- /* eat leading spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
- /* empty */;
- }
-
- sn->bv_val = x.bv_val;
- sn->bv_len = 0;
+ if ( numdquotes == 0 ) {
+ ber_dupbv_x( &ni, is, ctx );
- if( sn->bv_val[0] == '-' ) {
- neg++;
- sn->bv_len++;
- }
+ } else {
+ ber_int_t src, dst;
- if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
- sn->bv_val[1] == 'X' )) {
- is_hex = 1;
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
- }
- } else if ( sn->bv_val[0] == '\'' ) {
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+ ni.bv_len = is->bv_len - numdquotes;
+ ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
+ for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
+ if ( is->bv_val[src] == '"' ) {
+ src++;
}
- if ( sn->bv_val[sn->bv_len] == '\'' &&
- sn->bv_val[sn->bv_len+1] == 'H' )
- is_hex = 1;
- else
- return LDAP_INVALID_SYNTAX;
- sn->bv_len += 2;
- } else {
- for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
- if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
- }
- }
-
- if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
- if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
- return LDAP_INVALID_SYNTAX;
+ ni.bv_val[dst] = is->bv_val[src];
}
-
- x.bv_val += sn->bv_len;
- x.bv_len -= sn->bv_len;
-
- } else return LDAP_INVALID_SYNTAX;
-
- /* eat trailing spaces */
- for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
- /* empty */;
+ ni.bv_val[dst] = '\0';
}
-
- /* should have no characters left... */
- if( x.bv_len ) return LDAP_INVALID_SYNTAX;
-
- ber_dupbv_x( &ni, is, ctx );
+
*is = ni;
-
- /* need to handle double dquotes here */
}
+
return 0;
}
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
- if ( rc )
- return rc;
+ if ( rc ) {
+ goto done;
+ }
/* validate DN -- doesn't handle double dquote */
rc = dnValidate( NULL, &i );
- if( rc )
+ if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
+ }
- if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, NULL );
}
- Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
- 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
+ in->bv_val, rc, 0 );
+
+done:;
return rc;
}
-int
+static int
serialNumberAndIssuerPretty(
Syntax *syntax,
struct berval *in,
struct berval *out,
void *ctx )
{
- int n, rc;
- struct berval sn, i, ni;
+ int rc;
+ struct berval sn, i, ni = BER_BVNULL;
+ char *p;
assert( in != NULL );
assert( out != NULL );
+ BER_BVZERO( out );
+
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
- if ( rc )
- return rc;
+ if ( rc ) {
+ goto done;
+ }
rc = dnPretty( syntax, &i, &ni, ctx );
- if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
- if( rc ) return LDAP_INVALID_SYNTAX;
+ if ( rc ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
/* make room from sn + "$" */
out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
+ sn.bv_len + ni.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
- if( out->bv_val == NULL ) {
+ if ( out->bv_val == NULL ) {
out->bv_len = 0;
- slap_sl_free( ni.bv_val, ctx );
- return LDAP_OTHER;
+ rc = LDAP_OTHER;
+ goto done;
}
- n = 0;
- AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
- STRLENOF("{ serialNumber "));
- n = STRLENOF("{ serialNumber ");
+ p = out->bv_val;
+ p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
+ p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
+ p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
+ p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
- AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
- n += sn.bv_len;
+ assert( p - out->bv_val == out->bv_len );
- AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
- n += STRLENOF(", issuer rdnSequence:\"");
+done:;
+ Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
+ in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
- AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
- n += ni.bv_len;
+ slap_sl_free( ni.bv_val, ctx );
- AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
- n += STRLENOF("\" }");
+ return LDAP_SUCCESS;
+}
- out->bv_val[n] = '\0';
+static int
+slap_bin2hex(
+ struct berval *in,
+ struct berval *out,
+ void *ctx )
- assert( n == out->bv_len );
+{
+ /* Use hex format. '123456789abcdef'H */
+ unsigned char *ptr, zero = '\0';
+ char *sptr;
+ int first;
+ int i;
+ ber_len_t len, nlen;
- Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
- out->bv_val, 0, 0 );
+ assert( in != NULL );
+ assert( !BER_BVISNULL( in ) );
+ assert( out != NULL );
+ assert( !BER_BVISNULL( out ) );
- slap_sl_free( ni.bv_val, ctx );
+ ptr = (unsigned char *)in->bv_val;
+ len = in->bv_len;
- return LDAP_SUCCESS;
+ /* Check for minimal encodings */
+ if ( len > 1 ) {
+ if ( ptr[0] & 0x80 ) {
+ if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
+ return -1;
+ }
+
+ } else if ( ptr[0] == 0 ) {
+ if ( !( ptr[1] & 0x80 ) ) {
+ return -1;
+ }
+ len--;
+ ptr++;
+ }
+
+ } else if ( len == 0 ) {
+ /* FIXME: this should not be possible,
+ * since a value of zero would have length 1 */
+ len = 1;
+ ptr = &zero;
+ }
+
+ first = !( ptr[0] & 0xf0U );
+ nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
+ if ( nlen >= out->bv_len ) {
+ out->bv_val = slap_sl_malloc( nlen + 1, ctx );
+ }
+ sptr = out->bv_val;
+ *sptr++ = '\'';
+ i = 0;
+ if ( first ) {
+ sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
+ sptr++;
+ i = 1;
+ }
+ for ( ; i < len; i++ ) {
+ sprintf( sptr, "%02X", ptr[i] );
+ sptr += 2;
+ }
+ *sptr++ = '\'';
+ *sptr++ = 'H';
+ *sptr = '\0';
+
+ assert( sptr - out->bv_val == nlen );
+
+ out->bv_len = nlen;
+
+ return 0;
}
+#define SLAP_SN_BUFLEN (64)
+
/*
* This routine is called by certificateExactNormalize when
* certificateExactNormalize receives a search string instead of
struct berval *out,
void *ctx )
{
- struct berval sn, sn2, i, ni;
- char sbuf[64], *stmp = sbuf;
+ struct berval sn, sn2, sn3, i, ni;
+ char sbuf2[SLAP_SN_BUFLEN];
+ char sbuf3[SLAP_SN_BUFLEN];
+ char *p;
int rc;
- ber_len_t n;
assert( in != NULL );
assert( out != NULL );
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
- if ( rc )
+ if ( rc ) {
return rc;
+ }
rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
- if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
- if( rc ) return LDAP_INVALID_SYNTAX;
+ if ( rc ) {
+ return LDAP_INVALID_SYNTAX;
+ }
/* Convert sn to canonical hex */
- if ( sn.bv_len > sizeof( sbuf )) {
- stmp = slap_sl_malloc( sn.bv_len, ctx );
+ sn2.bv_val = sbuf2;
+ if ( sn.bv_len > sizeof( sbuf2 ) ) {
+ sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
}
- sn2.bv_val = stmp;
sn2.bv_len = sn.bv_len;
if ( lutil_str2bin( &sn, &sn2, ctx )) {
rc = LDAP_INVALID_SYNTAX;
- goto leave;
+ goto func_leave;
+ }
+
+ sn3.bv_val = sbuf3;
+ sn3.bv_len = sizeof(sbuf3);
+ if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto func_leave;
}
- /* make room for sn + "$" */
out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
- + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
+ + sn3.bv_len + ni.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
- if( out->bv_val == NULL ) {
+ if ( out->bv_val == NULL ) {
out->bv_len = 0;
- slap_sl_free( ni.bv_val, ctx );
rc = LDAP_OTHER;
- goto leave;
- }
-
- n = 0;
- AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
- STRLENOF( "{ serialNumber " ));
- n = STRLENOF( "{ serialNumber " );
-
- AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
- {
- int j;
- unsigned char *v = (unsigned char *)sn2.bv_val;
- out->bv_val[n++] = '\'';
- for ( j = 0; j < sn2.bv_len; j++ ) {
- snprintf( &out->bv_val[n], out->bv_len - n + 1,
- "%02X", v[j] );
- n += 2;
- }
- out->bv_val[n++] = '\'';
- out->bv_val[n++] = 'H';
+ goto func_leave;
}
- AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
- n += STRLENOF( ", issuer rdnSequence:\"" );
+ p = out->bv_val;
- AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
- n += ni.bv_len;
+ p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
+ p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
+ p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
+ p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
- AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
- n += STRLENOF( "\" }" );
+ assert( p - out->bv_val == out->bv_len );
- out->bv_val[n] = '\0';
+func_leave:
+ Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
+ in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
- assert( n == out->bv_len );
+ if ( sn2.bv_val != sbuf2 ) {
+ slap_sl_free( sn2.bv_val, ctx );
+ }
- Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
- out->bv_val, 0, 0 );
+ if ( sn3.bv_val != sbuf3 ) {
+ slap_sl_free( sn3.bv_val, ctx );
+ }
-leave:
- if ( stmp != sbuf )
- slap_sl_free( stmp, ctx );
slap_sl_free( ni.bv_val, ctx );
return rc;
ber_tag_t tag;
ber_len_t len;
ber_int_t i;
- char serialbuf[64], *serial = serialbuf;
- ber_len_t seriallen;
+ char serialbuf2[SLAP_SN_BUFLEN];
+ struct berval sn, sn2 = BER_BVNULL;
struct berval issuer_dn = BER_BVNULL, bvdn;
- unsigned char *p;
+ char *p;
int rc = LDAP_INVALID_SYNTAX;
- if( BER_BVISEMPTY( val ) ) goto done;
+ assert( val != NULL );
+
+ Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
+ val->bv_val, val->bv_len, 0 );
- if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
- return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
+ if ( BER_BVISEMPTY( val ) ) goto done;
+
+ if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
+ return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
}
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
/* NOTE: move the test here from certificateValidate,
* so that we can validate certs with serial longer
* than sizeof(ber_int_t) */
- tag = ber_peek_tag( ber, &len ); /* serial */
-
- /* Use hex format. '123456789abcdef'H
- */
- {
- unsigned char *ptr;
- char *sptr;
-
- tag = ber_skip_tag( ber, &len );
- ptr = (unsigned char *)ber->ber_ptr;
- ber_skip_data( ber, len );
-
- /* Check for minimal encodings */
- if ( len > 1 ) {
- if ( ptr[0] & 0x80 ) {
- if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
- return LDAP_INVALID_SYNTAX;
- } else if ( ptr[0] == 0 ) {
- if (!( ptr[1] & 0x80 ))
- return LDAP_INVALID_SYNTAX;
- }
- }
-
- seriallen = len * 2 + 4; /* quotes, H, NUL */
- if ( seriallen > sizeof( serialbuf ))
- serial = slap_sl_malloc( seriallen, ctx );
- sptr = serial;
- *sptr++ = '\'';
- for ( i = 0; i<len; i++ ) {
- sprintf( sptr, "%02X", ptr[i] );
- sptr += 2;
- }
- *sptr++ = '\'';
- *sptr++ = 'H';
- seriallen--;
+ tag = ber_skip_tag( ber, &len ); /* serial */
+ sn.bv_len = len;
+ sn.bv_val = (char *)ber->ber_ptr;
+ sn2.bv_val = serialbuf2;
+ sn2.bv_len = sizeof(serialbuf2);
+ if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
}
+ ber_skip_data( ber, len );
+
tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len ); /* IssuerDN */
bvdn.bv_len = val->bv_len - len;
rc = dnX509normalize( &bvdn, &issuer_dn );
- if( rc != LDAP_SUCCESS ) goto done;
+ if ( rc != LDAP_SUCCESS ) goto done;
normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
- + seriallen + issuer_dn.bv_len;
- normalized->bv_val = ch_malloc(normalized->bv_len+1);
+ + sn2.bv_len + issuer_dn.bv_len;
+ normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
+
+ p = normalized->bv_val;
+
+ p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
+ p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
+ p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
+ p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
+
+ rc = LDAP_SUCCESS;
+
+done:
+ Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
+ val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
+
+ if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
+ if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
+
+ return rc;
+}
+
+/* X.509 PKI certificateList stuff */
+static int
+checkTime( struct berval *in, struct berval *out )
+{
+ int i;
+ char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
+ struct berval bv;
+
+ assert( in != NULL );
+ assert( !BER_BVISNULL( in ) );
+ assert( !BER_BVISEMPTY( in ) );
+
+ if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
+ return -1;
+ }
+
+ if ( out != NULL ) {
+ assert( !BER_BVISNULL( out ) );
+ assert( out->bv_len >= sizeof( buf ) );
+ bv.bv_val = out->bv_val;
+
+ } else {
+ bv.bv_val = buf;
+ }
+
+ for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
+ if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
+ }
+
+ if ( in->bv_val[i] != 'Z' ) {
+ return -1;
+ }
+ i++;
+
+ if ( i != in->bv_len ) {
+ return -1;
+ }
+
+ if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
+ lutil_strncopy( bv.bv_val, in->bv_val, i );
+ bv.bv_len = i;
+
+ } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
+ char *p = bv.bv_val;
+ if ( in->bv_val[0] < '7' ) {
+ p = lutil_strcopy( p, "20" );
+
+ } else {
+ p = lutil_strcopy( p, "19" );
+ }
+ lutil_strncopy( p, in->bv_val, i );
+ bv.bv_len = 2 + i;
+
+ } else {
+ return -1;
+ }
+
+ i = generalizedTimeValidate( NULL, &bv );
+ if ( i == LDAP_SUCCESS && out != NULL ) {
+ out->bv_len = bv.bv_len;
+ }
+
+ return i != LDAP_SUCCESS;
+}
+
+static int
+issuerAndThisUpdateCheck(
+ struct berval *in,
+ struct berval *is,
+ struct berval *tu,
+ void *ctx )
+{
+ int numdquotes = 0;
+ struct berval x = *in;
+ struct berval ni = BER_BVNULL;
+ /* Parse GSER format */
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_ISSUER = 0x1,
+ HAVE_THISUPDATE = 0x2,
+ HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
+ } have = HAVE_NONE;
+
+
+ if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
+
+ if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ x.bv_val++;
+ x.bv_len -= STRLENOF("{}");
+
+ do {
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
+ }
+
+ /* should be at issuer or thisUpdate */
+ if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
+ if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
+
+ /* parse issuer */
+ x.bv_val += STRLENOF("issuer");
+ x.bv_len -= STRLENOF("issuer");
+
+ if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
+
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
+ }
+
+ /* For backward compatibility, this part is optional */
+ if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ x.bv_val += STRLENOF("rdnSequence:");
+ x.bv_len -= STRLENOF("rdnSequence:");
+
+ if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
+
+ is->bv_val = x.bv_val;
+ is->bv_len = 0;
+
+ for ( ; is->bv_len < x.bv_len; ) {
+ if ( is->bv_val[is->bv_len] != '"' ) {
+ is->bv_len++;
+ continue;
+ }
+ if ( is->bv_val[is->bv_len+1] == '"' ) {
+ /* double dquote */
+ is->bv_len += 2;
+ continue;
+ }
+ break;
+ }
+ x.bv_val += is->bv_len + 1;
+ x.bv_len -= is->bv_len + 1;
+
+ have |= HAVE_ISSUER;
+
+ } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
+ {
+ if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
+
+ /* parse thisUpdate */
+ x.bv_val += STRLENOF("thisUpdate");
+ x.bv_len -= STRLENOF("thisUpdate");
+
+ if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
+
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
+ }
+
+ if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
+ x.bv_val++;
+ x.bv_len--;
+
+ tu->bv_val = x.bv_val;
+ tu->bv_len = 0;
+
+ for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
+ if ( tu->bv_val[tu->bv_len] == '"' ) {
+ break;
+ }
+ }
+ x.bv_val += tu->bv_len + 1;
+ x.bv_len -= tu->bv_len + 1;
+
+ have |= HAVE_THISUPDATE;
+
+ } else {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* eat leading spaces */
+ for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
+ /* empty */;
+ }
+
+ if ( have == HAVE_ALL ) {
+ break;
+ }
+
+ if ( x.bv_val[0] != ',' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ x.bv_val++;
+ x.bv_len--;
+ } while ( 1 );
+
+ /* should have no characters left... */
+ if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
+
+ if ( numdquotes == 0 ) {
+ ber_dupbv_x( &ni, is, ctx );
+
+ } else {
+ ber_int_t src, dst;
+
+ ni.bv_len = is->bv_len - numdquotes;
+ ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
+ for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
+ if ( is->bv_val[src] == '"' ) {
+ src++;
+ }
+ ni.bv_val[dst] = is->bv_val[src];
+ }
+ ni.bv_val[dst] = '\0';
+ }
+
+ *is = ni;
+
+ return 0;
+}
+
+static int
+issuerAndThisUpdateValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int rc;
+ struct berval i, tu;
+
+ Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
+ in->bv_val, 0, 0 );
+
+ rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
+ if ( rc ) {
+ goto done;
+ }
+
+ /* validate DN -- doesn't handle double dquote */
+ rc = dnValidate( NULL, &i );
+ if ( rc ) {
+ rc = LDAP_INVALID_SYNTAX;
+
+ } else if ( checkTime( &tu, NULL ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ }
+
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ slap_sl_free( i.bv_val, NULL );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
+ in->bv_val, rc, 0 );
+
+done:;
+ return rc;
+}
+
+static int
+issuerAndThisUpdatePretty(
+ Syntax *syntax,
+ struct berval *in,
+ struct berval *out,
+ void *ctx )
+{
+ int rc;
+ struct berval i, tu, ni = BER_BVNULL;
+ char *p;
+
+ assert( in != NULL );
+ assert( out != NULL );
+
+ BER_BVZERO( out );
+
+ Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
+ in->bv_val, 0, 0 );
+
+ rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
+ if ( rc ) {
+ goto done;
+ }
+
+ rc = dnPretty( syntax, &i, &ni, ctx );
+
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ slap_sl_free( i.bv_val, ctx );
+ }
+
+ if ( rc || checkTime( &tu, NULL ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+ /* make room */
+ out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
+ + ni.bv_len + tu.bv_len;
+ out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
+
+ if ( out->bv_val == NULL ) {
+ out->bv_len = 0;
+ rc = LDAP_OTHER;
+ goto done;
+ }
- p = (unsigned char *)normalized->bv_val;
+ p = out->bv_val;
+ p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
+ p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strcopy( p, "\", thisUpdate \"" );
+ p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
- AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
- p += STRLENOF( "{ serialNumber " );
+ assert( p - out->bv_val == out->bv_len );
- AC_MEMCPY(p, serial, seriallen);
- p += seriallen;
+done:;
+ Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
+ in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
- AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
- p += STRLENOF( ", issuer rdnSequence:\"" );
+ slap_sl_free( ni.bv_val, ctx );
+
+ return rc;
+}
+
+static int
+issuerAndThisUpdateNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *in,
+ struct berval *out,
+ void *ctx )
+{
+ struct berval i, ni, tu, tu2;
+ char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
+ char *p;
+ int rc;
+
+ assert( in != NULL );
+ assert( out != NULL );
+
+ Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
+ in->bv_val, 0, 0 );
+
+ rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
+ if ( rc ) {
+ return rc;
+ }
+
+ rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
+
+ if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+ slap_sl_free( i.bv_val, ctx );
+ }
+
+ tu2.bv_val = sbuf;
+ tu2.bv_len = sizeof( sbuf );
+ if ( rc || checkTime( &tu, &tu2 ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
+ + ni.bv_len + tu2.bv_len;
+ out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
+
+ if ( out->bv_val == NULL ) {
+ out->bv_len = 0;
+ rc = LDAP_OTHER;
+ goto func_leave;
+ }
+
+ p = out->bv_val;
+
+ p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
+ p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strcopy( p, "\", thisUpdate \"" );
+ p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
+
+ assert( p - out->bv_val == out->bv_len );
+
+func_leave:
+ Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
+ in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
+
+ slap_sl_free( ni.bv_val, ctx );
+
+ return rc;
+}
+
+static int
+certificateListExactNormalize(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+ ber_tag_t tag;
+ ber_len_t len;
+ ber_int_t version;
+ struct berval issuer_dn = BER_BVNULL, bvdn,
+ thisUpdate, bvtu;
+ char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
+ int rc = LDAP_INVALID_SYNTAX;
- AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
- p += issuer_dn.bv_len;
+ assert( val != NULL );
+
+ Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
+ val->bv_val, val->bv_len, 0 );
- AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
- p += STRLENOF( "\" }" );
+ if ( BER_BVISEMPTY( val ) ) goto done;
- *p = '\0';
+ if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
+ return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
+ }
- Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
- normalized->bv_val, NULL, NULL );
+ assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
+
+ ber_init2( ber, val, LBER_USE_DER );
+ tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_skip_tag( ber, &len ); /* Sequence */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ tag = ber_peek_tag( ber, &len );
+ /* Optional version */
+ if ( tag == LBER_INTEGER ) {
+ tag = ber_get_int( ber, &version );
+ assert( tag == LBER_INTEGER );
+ if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
+ }
+ tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ ber_skip_data( ber, len );
+
+ tag = ber_peek_tag( ber, &len ); /* IssuerDN */
+ if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ len = ber_ptrlen( ber );
+ bvdn.bv_val = val->bv_val + len;
+ bvdn.bv_len = val->bv_len - len;
+ tag = ber_skip_tag( ber, &len );
+ ber_skip_data( ber, len );
+
+ tag = ber_skip_tag( ber, &len ); /* thisUpdate */
+ /* Time is a CHOICE { UTCTime, GeneralizedTime } */
+ if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
+ bvtu.bv_val = (char *)ber->ber_ptr;
+ bvtu.bv_len = len;
+
+ rc = dnX509normalize( &bvdn, &issuer_dn );
+ if ( rc != LDAP_SUCCESS ) goto done;
+
+ thisUpdate.bv_val = tubuf;
+ thisUpdate.bv_len = sizeof(tubuf);
+ if ( checkTime( &bvtu, &thisUpdate ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+ normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
+ + issuer_dn.bv_len + thisUpdate.bv_len;
+ normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
+
+ p = normalized->bv_val;
+
+ p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
+ p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
+ p = lutil_strcopy( p, "\", thisUpdate \"" );
+ p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
+ p = lutil_strcopy( p, /*{*/ "\" }" );
rc = LDAP_SUCCESS;
done:
+ Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
+ val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
+
if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
- if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
return rc;
}
return hexValidate( NULL, &bv );
}
+/* Normalize a CSN in OpenLDAP 2.1 format */
+static int
+csnNormalize21(
+ slap_mask_t usage,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ struct berval gt, cnt, sid, mod;
+ struct berval bv;
+ char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
+ char *ptr;
+ int i;
+
+ assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
+ assert( !BER_BVISEMPTY( val ) );
+
+ gt = *val;
+
+ ptr = ber_bvchr( >, '#' );
+ if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ gt.bv_len = ptr - gt.bv_val;
+ if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ cnt.bv_val = ptr + 1;
+ cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &cnt, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ cnt.bv_len = ptr - cnt.bv_val;
+ if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ cnt.bv_val += STRLENOF( "0x" );
+ cnt.bv_len -= STRLENOF( "0x" );
+
+ sid.bv_val = ptr + 1;
+ sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
+
+ ptr = ber_bvchr( &sid, '#' );
+ if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ sid.bv_len = ptr - sid.bv_val;
+ if ( sid.bv_len != STRLENOF( "0" ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ mod.bv_val = ptr + 1;
+ mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
+ if ( mod.bv_len != STRLENOF( "0000" ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
+ bv.bv_val = buf;
+
+ ptr = bv.bv_val;
+ ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
+ ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
+ STRLENOF( "MM" ) );
+ ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
+ STRLENOF( "SS" ) );
+ ptr = lutil_strcopy( ptr, ".000000Z#00" );
+ ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
+ *ptr++ = '#';
+ *ptr++ = '0';
+ *ptr++ = '0';
+ *ptr++ = sid.bv_val[ 0 ];
+ *ptr++ = '#';
+ *ptr++ = '0';
+ *ptr++ = '0';
+ for ( i = 0; i < mod.bv_len; i++ ) {
+ *ptr++ = TOLOWER( mod.bv_val[ i ] );
+ }
+ *ptr = '\0';
+
+ assert( ptr - bv.bv_val == bv.bv_len );
+
+ if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ ber_dupbv_x( normalized, &bv, ctx );
+
+ return LDAP_SUCCESS;
+}
+
/* Normalize a CSN in OpenLDAP 2.3 format */
static int
csnNormalize23(
void *ctx )
{
struct berval gt, cnt, sid, mod;
+ struct berval bv;
+ char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
char *ptr;
int i;
return LDAP_INVALID_SYNTAX;
}
- normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
- normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
+ bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
+ bv.bv_val = buf;
- ptr = normalized->bv_val;
+ ptr = bv.bv_val;
ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
ptr = lutil_strcopy( ptr, ".000000Z#" );
ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
}
*ptr = '\0';
- if ( ptr - normalized->bv_val != normalized->bv_len ) {
- ber_memfree_x( normalized->bv_val, ctx );
+ assert( ptr - bv.bv_val == bv.bv_len );
+ if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
+ ber_dupbv_x( normalized, &bv, ctx );
+
return LDAP_SUCCESS;
}
return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
}
+ if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
+ /* Openldap 2.1 */
+
+ return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
+ }
+
if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
return LDAP_INVALID_SYNTAX;
}
if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
- if( val->bv_val[0] != '(' /*')'*/ &&
- val->bv_val[0] != '{' /*'}'*/ )
+ if( ! ( val->bv_val[0] == '(' /*')'*/
+ && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
+ && ! ( val->bv_val[0] == '{' /*'}'*/
+ && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
{
return LDAP_INVALID_SYNTAX;
}
/* grab next word */
comp.bv_val = &val->bv_val[len];
- len = val->bv_len - len;
+ len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
for( comp.bv_len = 0;
!ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
comp.bv_len++ )
{"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
0, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
- 0, NULL, UTF8StringValidate, NULL},
+ 0, NULL, postalAddressValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
{"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
- SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL,
+ issuerAndThisUpdateValidate,
+ issuerAndThisUpdatePretty},
{"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
"1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
NULL
};
+char *certificateListExactMatchSyntaxes[] = {
+ "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
+ NULL
+};
#ifdef LDAP_COMP_MATCH
char *componentFilterMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
+ "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
NULL
};
#endif
* 2.5.13.33* keywordMatch
* 2.5.13.36+ certificatePairExactMatch
* 2.5.13.37+ certificatePairMatch
- * 2.5.13.38+ certificateListExactMatch
- * 2.5.13.39+ certificateListMatch
* 2.5.13.40+ algorithmIdentifierMatch
* 2.5.13.41* storedPrefixMatch
* 2.5.13.42 attributeCertificateMatch
{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL },
+ NULL, postalAddressNormalize, octetStringMatch,
+ octetStringIndexer, octetStringFilter,
+ NULL },
{"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
NULL, NULL, NULL, NULL, NULL,
NULL },
+ {"( 2.5.13.38 NAME 'certificateListExactMatch' "
+ "SYNTAX 1.3.6.1.1.15.5 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
+ NULL, certificateListExactNormalize, octetStringMatch,
+ octetStringIndexer, octetStringFilter,
+ NULL },
+
+ {"( 2.5.13.39 NAME 'certificateListMatch' "
+ "SYNTAX 1.3.6.1.1.15.6 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL },
+
{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,