Commit 68d561a9 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Add limited LDAP_INVALID_DN_SYNTAX support. dn_normalize{,_case}() now returns

NULL does not meet basic syntax rules.
parent 3f91cffa
......@@ -360,7 +360,10 @@ acl_access_allowed(
*/
/* see if asker is listed in dnattr */
string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches);
(void) dn_normalize_case(buf);
if ( dn_normalize_case(buf) == NULL ) {
/* did not expand to a valid dn */
continue;
}
if (backend_group(be, e, buf, op->o_ndn,
b->a_group_oc, b->a_group_at) != 0)
......
......@@ -26,7 +26,7 @@ int
do_add( Connection *conn, Operation *op )
{
BerElement *ber = op->o_ber;
char *dn, *last;
char *dn, *ndn, *last;
ber_len_t len;
ber_tag_t tag;
Entry *e;
......@@ -62,10 +62,21 @@ do_add( Connection *conn, Operation *op )
return -1;
}
ndn = ch_strdup( dn );
if ( dn_normalize_case( ndn ) == NULL ) {
Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn, 0, 0 );
send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, NULL,
"invalid DN", NULL, NULL );
free( dn );
free( ndn );
return LDAP_INVALID_DN_SYNTAX;
}
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
e->e_dn = dn;
e->e_ndn = dn_normalize_case( ch_strdup( dn ) );
e->e_ndn = ndn;
e->e_private = NULL;
dn = NULL;
......
......@@ -358,7 +358,8 @@ bdb2i_cache_find_entry_dn2id(
int count = 0;
e.e_dn = dn;
e.e_ndn = dn_normalize_case( ch_strdup( dn ) );
e.e_ndn = ch_strdup( dn )
(void) dn_normalize_case( e.e_ndn );
try_again:
/* set cache mutex */
......
......@@ -36,7 +36,7 @@ bdb2i_dn2id_add(
}
dn = ch_strdup( dn );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
key.dptr = dn;
key.dsize = strlen( dn ) + 1;
......@@ -71,7 +71,7 @@ bdb2i_dn2id(
dn = ch_strdup( dn );
Debug( LDAP_DEBUG_TRACE, "=> bdb2i_dn2id( \"%s\" )\n", dn, 0, 0 );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
/* first check the cache */
if ( (id = bdb2i_cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
......@@ -133,7 +133,7 @@ bdb2i_dn2id_delete(
}
dn = ch_strdup( dn );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
key.dptr = dn;
key.dsize = strlen( dn ) + 1;
......
......@@ -170,7 +170,8 @@ bdb2i_back_modrdn_internal(
"ldbm_back_modrdn: new parent requested...\n",
0, 0, 0 );
np_ndn = dn_normalize_case( ch_strdup( np_dn ) );
np_ndn = ch_strdup( np_dn );
(void) dn_normalize_case( np_ndn );
/* newSuperior == oldParent?, if so ==> ERROR */
......@@ -218,7 +219,8 @@ bdb2i_back_modrdn_internal(
build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
new_ndn = ch_strdup( new_dn );
(void) dn_normalize_case( new_ndn );
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
new_ndn, 0, 0 );
......@@ -321,7 +323,9 @@ bdb2i_back_modrdn_internal(
}
#ifdef DNS_DN
if ( dn_type( old_rdn ) == DN_X500 ) {
#endif
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
0, 0, 0 );
......@@ -383,6 +387,7 @@ bdb2i_back_modrdn_internal(
}/* if (deleteoldrdn) */
#ifdef DNS_DN
} else {
......@@ -394,6 +399,7 @@ bdb2i_back_modrdn_internal(
0, 0, 0 );
}
#endif
/* modify memory copy of entry */
if ( bdb2i_back_modify_internal( be, conn, op, dn, &mod[0], e )
......
......@@ -141,7 +141,8 @@ ldap_send_entry(
struct berval *dummy = NULL;
ent.e_dn = ldap_get_dn(lc->ld, e);
ent.e_ndn = dn_normalize_case( ch_strdup( ent.e_dn));
ent.e_ndn = ch_strdup( ent.e_dn);
(void) dn_normalize_case( ent.e_ndn );
ent.e_id = 0;
ent.e_attrs = 0;
ent.e_private = 0;
......
......@@ -439,7 +439,8 @@ cache_find_entry_dn2id(
int count = 0;
e.e_dn = dn;
e.e_ndn = dn_normalize_case( ch_strdup( dn ) );
e.e_ndn = ch_strdup( dn );
(void) dn_normalize_case( e.e_ndn );
try_again:
/* set cache mutex */
......
......@@ -36,7 +36,7 @@ dn2id_add(
}
dn = ch_strdup( dn );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
key.dptr = dn;
key.dsize = strlen( dn ) + 1;
......@@ -71,7 +71,7 @@ dn2id(
dn = ch_strdup( dn );
Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
/* first check the cache */
if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
......@@ -133,7 +133,7 @@ dn2id_delete(
}
dn = ch_strdup( dn );
dn_normalize_case( dn );
(void) dn_normalize_case( dn );
key.dptr = dn;
key.dsize = strlen( dn ) + 1;
......
......@@ -184,7 +184,8 @@ ldbm_back_modrdn(
"ldbm_back_modrdn: new parent requested...\n",
0, 0, 0 );
np_ndn = dn_normalize_case( ch_strdup( np_dn ) );
np_ndn = ch_strdup( np_dn );
(void) dn_normalize_case( np_ndn );
/* newSuperior == oldParent?, if so ==> ERROR */
/* newSuperior == entry being moved?, if so ==> ERROR */
......@@ -250,7 +251,8 @@ ldbm_back_modrdn(
build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
new_ndn = dn_normalize_case( ch_strdup(new_dn) );
new_ndn = ch_strdup(new_dn);
(void) dn_normalize_case( new_ndn );
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
new_ndn, 0, 0 );
......@@ -357,7 +359,9 @@ ldbm_back_modrdn(
}
#ifdef DNS_DN
if ( dn_type( old_rdn ) == DN_X500 ) {
#endif
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
0, 0, 0 );
......@@ -414,6 +418,7 @@ ldbm_back_modrdn(
old_rdn_val, 0, 0 );
}
#ifdef DNS_DN
} else {
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
0, 0, 0 );
......@@ -427,6 +432,7 @@ ldbm_back_modrdn(
goto return_results;
}
#endif
/* modify memory copy of entry */
if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e )
......
......@@ -238,7 +238,8 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn )
/* rdn attribute type should be a configuratable item */
sprintf( buf, "uid=%s,%s", pw->pw_name, be->be_suffix[0] );
e->e_dn = ch_strdup( buf );
e->e_ndn = dn_normalize_case( ch_strdup( buf ) );
e->e_ndn = ch_strdup( buf );
(void) dn_normalize_case( e->e_ndn );
val.bv_val = pw->pw_name;
val.bv_len = strlen( pw->pw_name );
......
......@@ -36,7 +36,7 @@ do_bind(
ber_int_t version;
ber_tag_t method;
char *mech;
char *cdn, *ndn;
char *dn, *ndn;
ber_tag_t tag;
int rc = LDAP_SUCCESS;
struct berval cred;
......@@ -44,7 +44,7 @@ do_bind(
Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
cdn = NULL;
dn = NULL;
ndn = NULL;
mech = NULL;
cred.bv_val = NULL;
......@@ -98,7 +98,7 @@ do_bind(
* }
*/
tag = ber_scanf( ber, "{iat" /*}*/, &version, &cdn, &method );
tag = ber_scanf( ber, "{iat" /*}*/, &version, &dn, &method );
if ( tag == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
......@@ -108,6 +108,15 @@ do_bind(
goto cleanup;
}
ndn = ch_strdup( dn );
if ( dn_normalize_case( ndn ) == NULL ) {
Debug( LDAP_DEBUG_ANY, "bind: invalid dn (%s)\n", dn, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
"invalid DN", NULL, NULL );
goto cleanup;
}
op->o_protocol = version;
if( method != LDAP_AUTH_SASL ) {
......@@ -145,14 +154,12 @@ do_bind(
if( method == LDAP_AUTH_SASL ) {
Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
cdn, mech, NULL );
dn, mech, NULL );
} else {
Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
version, cdn, method );
version, dn, method );
}
ndn = dn_normalize_case( ch_strdup( cdn ) );
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
op->o_connid, op->o_opid, ndn, method, 0 );
......@@ -277,8 +284,8 @@ do_bind(
if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_cdn = cdn;
cdn = NULL;
conn->c_cdn = dn;
dn = NULL;
if(edn != NULL) {
conn->c_dn = edn;
......@@ -306,8 +313,8 @@ do_bind(
}
cleanup:
if( cdn != NULL ) {
free( cdn );
if( dn != NULL ) {
free( dn );
}
if( ndn != NULL ) {
free( ndn );
......
......@@ -59,6 +59,15 @@ do_compare(
return -1;
}
if( dn_normalize_case( ndn ) == NULL ) {
Debug( LDAP_DEBUG_ANY, "do_compare: invalid dn (%s)\n", ndn, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
"invalid DN", NULL, NULL );
free( ndn );
ava_free( &ava, 0 );
return rc;
}
if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
free( ndn );
ava_free( &ava, 0 );
......@@ -71,8 +80,6 @@ do_compare(
Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
ndn, ava.ava_type, ava.ava_value.bv_val );
ndn = dn_normalize_case( ndn );
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d CMP dn=\"%s\" attr=\"%s\"\n",
op->o_connid, op->o_opid, ndn, ava.ava_type, 0 );
......
......@@ -264,7 +264,16 @@ read_config( char *fname )
fname, lineno, 0 );
} else {
be->be_root_dn = ch_strdup( cargv[1] );
be->be_root_ndn = dn_normalize_case( ch_strdup( cargv[1] ) );
be->be_root_ndn = ch_strdup( cargv[1] );
if( dn_normalize_case( be->be_root_ndn ) == NULL ) {
free( be->be_root_dn );
free( be->be_root_ndn );
Debug( LDAP_DEBUG_ANY,
"%s: line %d: rootdn DN is invalid\n",
fname, lineno, 0 );
return( 1 );
}
}
/* set super-secret magic database password */
......@@ -465,7 +474,12 @@ read_config( char *fname )
fname, lineno, 0 );
} else {
be->be_update_ndn = ch_strdup( cargv[1] );
(void) dn_normalize_case( be->be_update_ndn );
if( dn_normalize_case( be->be_update_ndn ) == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: updatedn DN is invalid\n",
fname, lineno, 0 );
return 1;
}
}
} else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
......
......@@ -42,7 +42,8 @@ config_info( Connection *conn, Operation *op )
e->e_attrs = NULL;
e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_CONFIG_DN ));
e->e_ndn = ch_strdup( SLAPD_CONFIG_DN );
(void) dn_normalize_case( e->e_ndn );
e->e_private = NULL;
for ( i = 0; i < nbackends; i++ ) {
......
......@@ -1022,7 +1022,8 @@ static int connection_op_activate( Connection *conn, Operation *op )
arg->co_op->o_bind_in_progress = conn->c_bind_in_progress;
arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
arg->co_op->o_ndn = dn_normalize_case( ch_strdup( arg->co_op->o_dn ) );
arg->co_op->o_ndn = ch_strdup( arg->co_op->o_dn );
(void) dn_normalize_case( arg->co_op->o_ndn );
arg->co_op->o_protocol = conn->c_protocol;
arg->co_op->o_connid = conn->c_connid;
......
......@@ -52,6 +52,14 @@ do_delete(
return -1;
}
if( dn_normalize_case( ndn ) == NULL ) {
Debug( LDAP_DEBUG_ANY, "do_delete: invalid dn (%s)\n", ndn, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
"invalid DN", NULL, NULL );
free( ndn );
return rc;
}
if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) {
free( ndn );
Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
......@@ -59,9 +67,6 @@ do_delete(
}
Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", ndn, 0, 0 );
dn_normalize_case( ndn );
Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", ndn, 0, 0 );
/*
......@@ -70,9 +75,9 @@ do_delete(
* if we don't hold it.
*/
if ( (be = select_backend( ndn )) == NULL ) {
free( ndn );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
free( ndn );
return rc;
}
......
......@@ -11,17 +11,18 @@
#include "slap.h"
#define B4TYPE 0
#define INTYPE 1
#define B4EQUAL 2
#define B4VALUE 3
#define INVALUE 4
#define INQUOTEDVALUE 5
#define B4SEPARATOR 6
#define B4LEADTYPE 0
#define B4TYPE 1
#define INTYPE 2
#define B4EQUAL 3
#define B4VALUE 4
#define INVALUE 5
#define INQUOTEDVALUE 6
#define B4SEPARATOR 7
/*
* dn_normalize - put dn into a canonical format. the dn is
* normalized in place, as well as returned.
* normalized in place, as well as returned if valid.
*/
char *
......@@ -30,12 +31,11 @@ dn_normalize( char *dn )
char *d, *s;
int state, gotesc;
/* Debug( LDAP_DEBUG_TRACE, "=> dn_normalize \"%s\"\n", dn, 0, 0 ); */
gotesc = 0;
state = B4TYPE;
state = B4LEADTYPE;
for ( d = s = dn; *s; s++ ) {
switch ( state ) {
case B4LEADTYPE:
case B4TYPE:
if ( ! SPACE( *s ) ) {
state = INTYPE;
......@@ -59,6 +59,7 @@ dn_normalize( char *dn )
} else if ( ! SPACE( *s ) ) {
/* not a valid dn - but what can we do here? */
*d++ = *s;
dn = NULL;
}
break;
case B4VALUE:
......@@ -106,6 +107,7 @@ dn_normalize( char *dn )
}
break;
default:
dn = NULL;
Debug( LDAP_DEBUG_ANY,
"dn_normalize - unknown state %d\n", state, 0, 0 );
break;
......@@ -118,24 +120,40 @@ dn_normalize( char *dn )
}
*d = '\0';
/* Debug( LDAP_DEBUG_TRACE, "<= dn_normalize \"%s\"\n", dn, 0, 0 ); */
if( gotesc ) {
/* shouldn't be left in escape */
dn = NULL;
}
/* check end state */
switch( state ) {
case B4LEADTYPE: /* looking for first type */
case B4SEPARATOR: /* looking for separator */
case INVALUE: /* inside value */
break;
default:
dn = NULL;
}
return( dn );
}
/*
* dn_normalize_case - put dn into a canonical form suitable for storing
* in a hash database. this involves normalizing the case as well as
* the format. the dn is normalized in place as well as returned.
* the format. the dn is normalized in place as well as returned if valid.
*/
char *
dn_normalize_case( char *dn )
{
str2upper( dn );
/* normalize format */
dn_normalize( dn );
dn = dn_normalize( dn );
/* and upper case it */
return( str2upper( dn ) );
return( dn );
}
/*
......@@ -239,6 +257,7 @@ char * dn_rdn(
dn = ch_strdup( dn );
#ifdef DNS_DN
/*
* no =, assume it is a dns name, like blah@some.domain.name
* if the blah@ part is there, return some.domain.name. if
......@@ -253,6 +272,7 @@ char * dn_rdn(
*s = '\0';
return( dn );
}
#endif
/*
* else assume it is an X.500-style name, which looks like
......@@ -312,6 +332,7 @@ dn_issuffix(
return( strcmp( dn + dnlen - suffixlen, suffix ) == 0 );
}
#ifdef DNS_DN
/*
* dn_type - tells whether the given dn is an X.500 thing or DNS thing
* returns (defined in slap.h): DN_DNS dns-style thing
......@@ -323,6 +344,7 @@ dn_type( char *dn )
{
return( strchr( dn, '=' ) == NULL ? DN_DNS : DN_X500 );
}
#endif
char *
str2upper( char *str )
......@@ -386,7 +408,7 @@ get_next_substring( char * s, char d )
s++;
}/* while ( *s && SPACE(*s) ) */
}
/* Copy word */
......@@ -398,13 +420,13 @@ get_next_substring( char * s, char d )
*str++ = *s++;
}/* while ( *s && (*s != d) ) */
}
*str = '\0';
return r;
}/* char * get_word() */
}
/* rdn_attr_type:
......@@ -421,7 +443,7 @@ char * rdn_attr_type( char * s )
return get_next_substring( s, '=' );
}/* char * rdn_attr_type() */
}
/* rdn_attr_value:
......@@ -443,11 +465,18 @@ rdn_attr_value( char * rdn )
return get_next_substring(++str, '\0');
}/* if ( (str = strpbrk( rdn, "=" )) != NULL ) */
}
return NULL;
}/* char * rdn_attr_value() */
}
int rdn_validate( const char * rdn )
{
/* just a simple check for now */
return strchr( rdn, '=' ) != NULL;
}
/* build_new_dn:
......@@ -471,12 +500,15 @@ build_new_dn( char ** new_dn, char *e_dn, char * p_dn, char * newrdn )
*new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
#ifdef DNS_DN
if ( dn_type( e_dn ) == DN_X500 ) {
#endif
strcpy( *new_dn, newrdn );
strcat( *new_dn, "," );
strcat( *new_dn, p_dn );
#ifdef DNS_DN
} else {
char *s;
......@@ -494,12 +526,13 @@ build_new_dn( char ** new_dn, char *e_dn, char * p_dn, char * newrdn )
sep[1] = '\0';
strcat( *new_dn, sep );