ITS#1712, rewritten dn_openssl2ldap(). Added dnDCEnormalize(), used by

dn_openssl2ldap() and sasl_external_x509dn_convert. Fixed realm handling
for foreign Kerberos realms embedded in usernames.
This commit is contained in:
Howard Chu 2002-04-16 08:46:25 +00:00
parent 03679b7ce5
commit 1bbd51da77
4 changed files with 147 additions and 112 deletions

View File

@ -829,3 +829,40 @@ dnIsSuffix(
/* compare */
return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
}
/*
* Convert a DN from X.500 format into a normalized DN
*/
int
dnDCEnormalize( char *dce, struct berval *out )
{
int rc;
LDAPDN *dn = NULL;
out->bv_val = NULL;
out->bv_len = 0;
rc = ldap_str2dn( dce, &dn, LDAP_DN_FORMAT_DCE );
if ( rc != LDAP_SUCCESS )
return rc;
/*
* Schema-aware rewrite
*/
if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
ldap_dnfree( dn );
return LDAP_INVALID_SYNTAX;
}
/*
* Back to string representation
*/
rc = ldap_dn2bv( dn, out, LDAP_DN_FORMAT_LDAPV3 );
ldap_dnfree( dn );
if ( rc != LDAP_SUCCESS ) {
rc = LDAP_INVALID_SYNTAX;
}
return rc;
}

View File

@ -404,6 +404,8 @@ LDAP_SLAPD_F (void) build_new_dn LDAP_P((
LDAP_SLAPD_F (void) dnParent LDAP_P(( struct berval *dn, struct berval *pdn ));
LDAP_SLAPD_F (int) dnDCEnormalize LDAP_P(( char *dce, struct berval *out ));
/*
* entry.c
*/

View File

@ -137,11 +137,11 @@ slap_sasl_log(
static struct berval ext_bv = { sizeof("EXTERNAL")-1, "EXTERNAL" };
int slap_sasl_getdn( Connection *conn, char *id,
int slap_sasl_getdn( Connection *conn, char *id, int len,
char *user_realm, struct berval *dn, int flags )
{
char *c1;
int rc, len, is_dn = 0;
int rc, is_dn = 0;
sasl_conn_t *ctx;
struct berval dn2;
@ -166,7 +166,7 @@ int slap_sasl_getdn( Connection *conn, char *id,
return( LDAP_SUCCESS );
}
ctx = conn->c_sasl_context;
len = strlen( id );
if ( len == 0 ) len = strlen( id );
/* An authcID needs to be converted to authzID form */
if( flags & FLAG_GETDN_AUTHCID ) {
@ -177,8 +177,7 @@ int slap_sasl_getdn( Connection *conn, char *id,
{
/* check SASL external for X.509 style DN and */
/* convert to dn:<dn> form */
dn->bv_val = ldap_dcedn2dn( id );
dn->bv_len = strlen(dn->bv_val);
dnDCEnormalize( id, dn );
is_dn = SET_DN;
} else {
@ -309,7 +308,7 @@ slap_sasl_checkpass(
/* XXX do we need to check sasldb as well? */
/* XXX can we do both steps at once? */
rc = slap_sasl_getdn( conn, (char *)username, NULL, &dn,
rc = slap_sasl_getdn( conn, (char *)username, 0, NULL, &dn,
FLAG_GETDN_AUTHCID | FLAG_GETDN_FINAL );
if ( rc != LDAP_SUCCESS ) {
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
@ -388,7 +387,7 @@ slap_sasl_canonicalize(
in ? in : "<empty>" );
#endif
rc = slap_sasl_getdn( conn, (char *)in, (char *)user_realm, &dn,
rc = slap_sasl_getdn( conn, (char *)in, inlen, (char *)user_realm, &dn,
(flags == SASL_CU_AUTHID) ? FLAG_GETDN_AUTHCID : FLAG_GETDN_AUTHZID );
if ( rc != LDAP_SUCCESS ) {
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
@ -441,7 +440,7 @@ slap_sasl_authorize(
Connection *conn = (Connection *)context;
struct berval authcDN, authzDN;
char *realm;
int rc, equal = 1;
int rc, equal = 1, ext = 0;
#ifdef NEW_LOGGING
LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
@ -456,11 +455,19 @@ slap_sasl_authorize(
if ( requested_user )
equal = !strcmp( auth_identity, requested_user );
realm = strchr( auth_identity, '@' );
if ( realm )
*realm++ = '\0';
/* If using SASL-EXTERNAL, don't modify the ID in any way */
if ( conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len
&& ( strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 )
&& auth_identity[0] == '/' ) {
ext = 1;
realm = NULL;
} else {
/* Else look for an embedded realm in the name */
realm = strchr( auth_identity, '@' );
if ( realm ) *realm++ = '\0';
}
rc = slap_sasl_getdn( conn, auth_identity, realm ? realm : (char *)def_realm,
rc = slap_sasl_getdn( conn, auth_identity, alen, realm ? realm : (char *)def_realm,
&authcDN, FLAG_GETDN_AUTHCID );
if ( realm )
realm[-1] = '@';
@ -480,11 +487,14 @@ slap_sasl_authorize(
return SASL_OK;
}
realm = strchr( requested_user, '@' );
if ( realm )
*realm++ = '\0';
if ( ext ) {
realm = NULL;
} else {
realm = strchr( requested_user, '@' );
if ( realm ) *realm++ = '\0';
}
rc = slap_sasl_getdn( conn, requested_user, realm ? realm : (char *)def_realm,
rc = slap_sasl_getdn( conn, requested_user, rlen, realm ? realm : (char *)def_realm,
&authzDN, FLAG_GETDN_AUTHZID );
if ( realm )
realm[-1] = '@';
@ -537,15 +547,15 @@ slap_sasl_authorize(
static int
slap_sasl_authorize(
void *context,
const char *authcid,
const char *authzid,
char *authcid,
char *authzid,
const char **user,
const char **errstr)
{
struct berval authcDN, authzDN;
int rc;
int rc, ext = 0;
Connection *conn = context;
char *realm;
char *realm, *xrealm;
*user = NULL;
@ -579,7 +589,17 @@ slap_sasl_authorize(
/* Convert the identities to DN's. If no authzid was given, client will
be bound as the DN matching their username */
rc = slap_sasl_getdn( conn, (char *)authcid, realm, &authcDN, FLAG_GETDN_AUTHCID );
if ( conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len
&& ( strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 )
&& authcid[0] == '/' ) {
ext = 1;
xrealm = NULL;
} else {
xrealm = strchr( authcid, '@' );
if ( xrealm ) *xrealm++ = '\0';
}
rc = slap_sasl_getdn( conn, (char *)authcid, 0, xrealm ? xrealm : realm, &authcDN, FLAG_GETDN_AUTHCID );
if ( xrealm ) xrealm[-1] = '@';
if( rc != LDAP_SUCCESS ) {
*errstr = ldap_err2string( rc );
return SASL_NOAUTHZ;
@ -598,7 +618,14 @@ slap_sasl_authorize(
*errstr = NULL;
return SASL_OK;
}
rc = slap_sasl_getdn( conn, (char *)authzid, realm, &authzDN, FLAG_GETDN_AUTHZID );
if ( ext ) {
xrealm = NULL;
} else {
xrealm = strchr( authzid, '@' );
if ( xrealm ) *xrealm++ = '\0';
}
rc = slap_sasl_getdn( conn, (char *)authzid, 0, xrealm ? xrealm : realm, &authzDN, FLAG_GETDN_AUTHZID );
if ( xrealm ) xrealm[-1] = '@';
if( rc != LDAP_SUCCESS ) {
ch_free( authcDN.bv_val );
*errstr = ldap_err2string( rc );
@ -1088,7 +1115,7 @@ int slap_sasl_bind(
NULL, "no SASL username", NULL, NULL );
} else {
rc = slap_sasl_getdn( conn, username, realm, edn, FLAG_GETDN_FINAL );
rc = slap_sasl_getdn( conn, username, 0, realm, edn, FLAG_GETDN_FINAL );
if( rc == LDAP_SUCCESS ) {
sasl_ssf_t *ssf = NULL;

View File

@ -3421,7 +3421,7 @@ char digit[] = "0123456789";
*/
static struct berval *
asn1_integer2str(ASN1_INTEGER *a)
asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
{
char buf[256];
char *p;
@ -3477,35 +3477,17 @@ asn1_integer2str(ASN1_INTEGER *a)
*--p = '-';
}
return ber_bvstrdup(p);
return ber_str2bv( p, 0, 1, bv );
}
/* Get a DN in RFC2253 format from a X509_NAME internal struct */
static struct berval *
dn_openssl2ldap(X509_NAME *name)
int
dn_openssl2ldap(X509_NAME *name, struct berval *out)
{
char issuer_dn[1024];
BIO *bio;
char buf[2048], *p;
bio = BIO_new(BIO_s_mem());
if ( !bio ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
"dn_openssl2ldap: error creating BIO_s_mem: %s\n",
ERR_error_string(ERR_get_error(),NULL)));
#else
Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
"error creating BIO: %s\n",
ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
#endif
return NULL;
}
X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
BIO_gets(bio, issuer_dn, 1024);
BIO_free(bio);
return ber_bvstrdup(issuer_dn);
p = X509_NAME_oneline( name, buf, sizeof( buf ) );
return dnDCEnormalize( p, out );
}
/*
@ -3519,9 +3501,8 @@ certificateExactConvert(
{
X509 *xcert;
unsigned char *p = in->bv_val;
struct berval *serial;
struct berval *issuer_dn;
struct berval *bv_tmp;
struct berval serial;
struct berval issuer_dn;
xcert = d2i_X509(NULL, &p, in->bv_len);
if ( !xcert ) {
@ -3537,39 +3518,27 @@ certificateExactConvert(
return LDAP_INVALID_SYNTAX;
}
serial = asn1_integer2str(xcert->cert_info->serialNumber);
if ( !serial ) {
if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
X509_free(xcert);
return LDAP_INVALID_SYNTAX;
}
issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
if ( !issuer_dn ) {
if ( dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
X509_free(xcert);
ber_bvfree(serial);
ber_memfree(serial.bv_val);
return LDAP_INVALID_SYNTAX;
}
/* Actually, dn_openssl2ldap returns in a normalized format, but
it is different from our normalized format */
bv_tmp = issuer_dn;
if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
X509_free(xcert);
ber_bvfree(serial);
ber_bvfree(bv_tmp);
return LDAP_INVALID_SYNTAX;
}
ber_bvfree(bv_tmp);
X509_free(xcert);
out->bv_len = serial->bv_len + issuer_dn->bv_len + sizeof(" $ ");
out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
out->bv_val = ch_malloc(out->bv_len);
p = out->bv_val;
AC_MEMCPY(p, serial->bv_val, serial->bv_len);
p += serial->bv_len;
AC_MEMCPY(p, serial.bv_val, serial.bv_len);
p += serial.bv_len;
AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
p += 3;
AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len);
p += issuer_dn->bv_len;
AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
p += issuer_dn.bv_len;
*p++ = '\0';
#ifdef NEW_LOGGING
@ -3582,8 +3551,8 @@ certificateExactConvert(
out->bv_val, NULL, NULL );
#endif
ber_bvfree(serial);
ber_bvfree(issuer_dn);
ber_memfree(serial.bv_val);
ber_memfree(issuer_dn.bv_val);
return LDAP_SUCCESS;
}
@ -3591,8 +3560,8 @@ certificateExactConvert(
static int
serial_and_issuer_parse(
struct berval *assertion,
struct berval **serial,
struct berval **issuer_dn
struct berval *serial,
struct berval *issuer_dn
)
{
char *begin;
@ -3617,18 +3586,20 @@ serial_and_issuer_parse(
bv.bv_len = end-begin+1;
bv.bv_val = begin;
*serial = ber_dupbv(NULL, &bv);
ber_dupbv(serial, &bv);
/* now extract the issuer, remember p was at the dollar sign */
begin = p+1;
end = assertion->bv_val+assertion->bv_len-1;
while (ASCII_SPACE(*begin))
begin++;
/* should we trim spaces at the end too? is it safe always? */
if ( issuer_dn ) {
begin = p+1;
end = assertion->bv_val+assertion->bv_len-1;
while (ASCII_SPACE(*begin))
begin++;
/* should we trim spaces at the end too? is it safe always? */
bv.bv_len = end-begin+1;
bv.bv_val = begin;
dnNormalize( NULL, &bv, issuer_dn );
bv.bv_len = end-begin+1;
bv.bv_val = begin;
dnNormalize2( NULL, &bv, issuer_dn );
}
return LDAP_SUCCESS;
}
@ -3644,10 +3615,10 @@ certificateExactMatch(
{
X509 *xcert;
unsigned char *p = value->bv_val;
struct berval *serial;
struct berval *issuer_dn;
struct berval *asserted_serial;
struct berval *asserted_issuer_dn;
struct berval serial;
struct berval issuer_dn;
struct berval asserted_serial;
struct berval asserted_issuer_dn;
int ret;
xcert = d2i_X509(NULL, &p, value->bv_len);
@ -3664,8 +3635,8 @@ certificateExactMatch(
return LDAP_INVALID_SYNTAX;
}
serial = asn1_integer2str(xcert->cert_info->serialNumber);
issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
asn1_integer2str(xcert->cert_info->serialNumber, &serial);
dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn);
X509_free(xcert);
@ -3678,8 +3649,8 @@ certificateExactMatch(
flags,
slap_schema.si_syn_integer,
slap_schema.si_mr_integerMatch,
serial,
asserted_serial);
&serial,
&asserted_serial);
if ( ret == LDAP_SUCCESS ) {
if ( *matchp == 0 ) {
/* We need to normalize everything for dnMatch */
@ -3688,29 +3659,29 @@ certificateExactMatch(
flags,
slap_schema.si_syn_distinguishedName,
slap_schema.si_mr_distinguishedNameMatch,
issuer_dn,
asserted_issuer_dn);
&issuer_dn,
&asserted_issuer_dn);
}
}
#ifdef NEW_LOGGING
LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
"certificateExactMatch: %d\n %s $ %s\n %s $ %s\n",
*matchp, serial->bv_val, issuer_dn->bv_val,
asserted_serial->bv_val, asserted_issuer_dn->bv_val));
*matchp, serial.bv_val, issuer_dn.bv_val,
asserted_serial.bv_val, asserted_issuer_dn.bv_val));
#else
Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
"%d\n\t\"%s $ %s\"\n",
*matchp, serial->bv_val, issuer_dn->bv_val );
*matchp, serial.bv_val, issuer_dn.bv_val );
Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
asserted_serial->bv_val, asserted_issuer_dn->bv_val,
asserted_serial.bv_val, asserted_issuer_dn.bv_val,
NULL );
#endif
ber_bvfree(serial);
ber_bvfree(issuer_dn);
ber_bvfree(asserted_serial);
ber_bvfree(asserted_issuer_dn);
ber_memfree(serial.bv_val);
ber_memfree(issuer_dn.bv_val);
ber_memfree(asserted_serial.bv_val);
ber_memfree(asserted_issuer_dn.bv_val);
return ret;
}
@ -3733,7 +3704,7 @@ static int certificateExactIndexer(
BerVarray keys;
X509 *xcert;
unsigned char *p;
struct berval * serial;
struct berval serial;
/* we should have at least one value at this point */
assert( values != NULL && values[0].bv_val != NULL );
@ -3762,12 +3733,12 @@ static int certificateExactIndexer(
return LDAP_INVALID_SYNTAX;
}
serial = asn1_integer2str(xcert->cert_info->serialNumber);
asn1_integer2str(xcert->cert_info->serialNumber, &serial);
X509_free(xcert);
integerNormalize( slap_schema.si_syn_integer,
serial,
&serial,
&keys[i] );
ber_bvfree(serial);
ber_memfree(serial.bv_val);
#ifdef NEW_LOGGING
LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
"certificateExactIndexer: returning: %s\n",
@ -3797,20 +3768,18 @@ static int certificateExactFilter(
BerVarray *keysp )
{
BerVarray keys;
struct berval *asserted_serial;
struct berval *asserted_issuer_dn;
struct berval asserted_serial;
serial_and_issuer_parse(assertValue,
&asserted_serial,
&asserted_issuer_dn);
NULL);
keys = ch_malloc( sizeof( struct berval ) * 2 );
integerNormalize( syntax, asserted_serial, &keys[0] );
integerNormalize( syntax, &asserted_serial, &keys[0] );
keys[1].bv_val = NULL;
*keysp = keys;
ber_bvfree(asserted_serial);
ber_bvfree(asserted_issuer_dn);
ber_memfree(asserted_serial.bv_val);
return LDAP_SUCCESS;
}
#endif