From 68d561a97b9f634f033eae0f2d9c7453ea02c4c7 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Thu, 22 Jul 1999 17:14:42 +0000 Subject: [PATCH] Add limited LDAP_INVALID_DN_SYNTAX support. dn_normalize{,_case}() now returns NULL does not meet basic syntax rules. --- servers/slapd/acl.c | 5 +- servers/slapd/add.c | 15 +++- servers/slapd/back-bdb2/cache.c | 3 +- servers/slapd/back-bdb2/dn2id.c | 6 +- servers/slapd/back-bdb2/modrdn.c | 10 ++- servers/slapd/back-ldap/search.c | 3 +- servers/slapd/back-ldbm/cache.c | 3 +- servers/slapd/back-ldbm/dn2id.c | 6 +- servers/slapd/back-ldbm/modrdn.c | 10 ++- servers/slapd/back-passwd/search.c | 3 +- servers/slapd/bind.c | 29 ++++--- servers/slapd/compare.c | 11 ++- servers/slapd/config.c | 18 ++++- servers/slapd/configinfo.c | 3 +- servers/slapd/connection.c | 3 +- servers/slapd/delete.c | 13 ++- servers/slapd/dn.c | 83 +++++++++++++------ servers/slapd/entry.c | 3 +- servers/slapd/modify.c | 10 ++- servers/slapd/modrdn.c | 89 +++++++++++---------- servers/slapd/monitor.c | 3 +- servers/slapd/proto-slap.h | 3 + servers/slapd/root_dse.c | 3 +- servers/slapd/schema.c | 3 +- servers/slapd/search.c | 7 +- servers/slapd/slap.h | 2 + servers/slapd/tools/ldif2id2children-bdb2.c | 9 ++- servers/slapd/tools/ldif2id2children.c | 9 ++- 28 files changed, 243 insertions(+), 122 deletions(-) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index e632c1a9f6..15bbcd4fba 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -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) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 683a7649c3..efb4e18d6d 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -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; diff --git a/servers/slapd/back-bdb2/cache.c b/servers/slapd/back-bdb2/cache.c index e13c918537..593c304351 100644 --- a/servers/slapd/back-bdb2/cache.c +++ b/servers/slapd/back-bdb2/cache.c @@ -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 */ diff --git a/servers/slapd/back-bdb2/dn2id.c b/servers/slapd/back-bdb2/dn2id.c index e77cabfa20..35b1081d2b 100644 --- a/servers/slapd/back-bdb2/dn2id.c +++ b/servers/slapd/back-bdb2/dn2id.c @@ -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; diff --git a/servers/slapd/back-bdb2/modrdn.c b/servers/slapd/back-bdb2/modrdn.c index 8054eed2c1..4460c06cdd 100644 --- a/servers/slapd/back-bdb2/modrdn.c +++ b/servers/slapd/back-bdb2/modrdn.c @@ -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 ) diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index c742248c5e..f6054fa66e 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -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; diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c index 85d3b07ef6..a355f7142e 100644 --- a/servers/slapd/back-ldbm/cache.c +++ b/servers/slapd/back-ldbm/cache.c @@ -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 */ diff --git a/servers/slapd/back-ldbm/dn2id.c b/servers/slapd/back-ldbm/dn2id.c index 377952acba..405ca65b69 100644 --- a/servers/slapd/back-ldbm/dn2id.c +++ b/servers/slapd/back-ldbm/dn2id.c @@ -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; diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index 1b8d49bbca..e7a7f83d03 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -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 ) diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c index cb1b9f4b29..08c20b8900 100644 --- a/servers/slapd/back-passwd/search.c +++ b/servers/slapd/back-passwd/search.c @@ -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 ); diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index c09d4098e7..74459983bb 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -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 ); diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index c617be2028..f3a8ae9c13 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -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 ); diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 3a9e7b4d61..e4d67fedde 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -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 ) { diff --git a/servers/slapd/configinfo.c b/servers/slapd/configinfo.c index 4d85b2b627..5d45069fa9 100644 --- a/servers/slapd/configinfo.c +++ b/servers/slapd/configinfo.c @@ -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++ ) { diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 036dde765f..504fe2cbfe 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -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; diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 2b2d41cfaa..aa0bbc4b21 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -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; } diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c index b9e2497117..a04cacfba9 100644 --- a/servers/slapd/dn.c +++ b/servers/slapd/dn.c @@ -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 ); - }/* if ( (s = strpbrk( dn, ".@" )) != NULL ) */ + } - }/* if ( *s != '.' && *s != '@' ) */ + } strcat( *new_dn, p_dn ); - }/* if ( dn_type( e_dn ) == DN_X500 ) {}else */ + } +#endif -}/* void build_new_dn() */ +} diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 563e01cec1..e0465230e9 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -110,7 +110,8 @@ str2entry( char *s ) e->e_id, e->e_ndn, value ); free( e->e_ndn ); } - e->e_ndn = dn_normalize_case( ch_strdup( value ) ); + e->e_ndn = ch_strdup( value ); + (void) dn_normalize_case( e->e_ndn ); continue; } diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 016033742c..2bf8ce5a5c 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -70,7 +70,7 @@ do_modify( */ if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) { - Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "do_modify: ber_scanf failed\n", 0, 0, 0 ); send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); return -1; @@ -78,7 +78,13 @@ do_modify( Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 ); - (void) dn_normalize_case( ndn ); + if( dn_normalize_case( ndn ) == NULL ) { + Debug( LDAP_DEBUG_ANY, "do_modify: 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; + } /* collect modifications & save for later */ modlist = NULL; diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 59ce22cdea..2f559de27d 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -77,6 +77,24 @@ do_modrdn( return -1; } + if( dn_normalize_case( ndn ) == NULL ) { + Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid dn (%s)\n", ndn, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, + "invalid DN", NULL, NULL ); + free( ndn ); + free( newrdn ); + return rc; + } + + if( !rdn_validate( newrdn ) ) { + Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n", newrdn, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, + "invalid RDN", NULL, NULL ); + free( ndn ); + free( newrdn ); + return rc; + } + /* Check for newSuperior parameter, if present scan it */ if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) { @@ -110,7 +128,18 @@ do_modrdn( send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); return -1; + } + + nnewSuperior = ch_strdup( newSuperior ); + if( dn_normalize_case( nnewSuperior ) == NULL ) { + Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid new superior (%s)\n", + newSuperior, 0, 0 ); + send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, + "invalid (new superior) DN", NULL, NULL ); + free( ndn ); + free( newrdn ); + return rc; } } @@ -124,6 +153,7 @@ do_modrdn( free( ndn ); free( newrdn ); free( newSuperior ); + free( nnewSuperior ); Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 ); send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); @@ -138,37 +168,6 @@ do_modrdn( return rc; } - if( newSuperior != NULL ) { - /* GET BACKEND FOR NEW SUPERIOR */ - - nnewSuperior = strdup( newSuperior ); - dn_normalize_case( nnewSuperior ); - - if ( (newSuperior_be = select_backend( nnewSuperior )) - == NULL ) { - - /* We do not have a backend for newSuperior so we send - * a referral. - * XXX: We may need to do something else here, not sure - * what though. - */ - - Debug( LDAP_DEBUG_ARGS, - "do_modrdn: cant find backend for=(%s)\n", - newSuperior, 0, 0 ); - - free( ndn ); - free( newrdn ); - free( newSuperior ); - free( nnewSuperior ); - send_ldap_result( conn, op, LDAP_REFERRAL, - NULL, NULL, default_referral, NULL ); - return 0; - } - } - - dn_normalize_case( ndn ); - Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MODRDN dn=\"%s\"\n", op->o_connid, op->o_opid, ndn, 0, 0 ); @@ -188,25 +187,27 @@ do_modrdn( return rc; } + /* Make sure that the entry being changed and the newSuperior are in * the same backend, otherwise we return an error. */ + if( newSuperior != NULL ) { + newSuperior_be = select_backend( nnewSuperior ); - if ( (newSuperior_be != NULL) && ( be != newSuperior_be) ) { + if ( newSuperior != be ) { + /* newSuperior is in same backend */ + rc = LDAP_AFFECTS_MULTIPLE_DSAS; - Debug( LDAP_DEBUG_ANY, "dn=(%s), newSuperior=(%s)\n", ndn, - newSuperior, 0 ); - - free( ndn ); - free( newrdn ); - free( newSuperior ); - free( nnewSuperior ); - - send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS, - NULL, NULL, NULL, NULL ); - - return rc; + send_ldap_result( conn, op, rc, + NULL, NULL, NULL, NULL ); + free( ndn ); + free( newrdn ); + free( newSuperior ); + free( nnewSuperior ); + + return rc; + } } /* diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index dff72f9690..891cbab2b1 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -46,7 +46,8 @@ monitor_info( Connection *conn, Operation *op ) /* initialize reader/writer lock */ e->e_attrs = NULL; e->e_dn = ch_strdup( SLAPD_MONITOR_DN ); - e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) ); + e->e_ndn = ch_strdup(SLAPD_MONITOR_DN); + (void) dn_normalize_case( e->e_ndn ); e->e_private = NULL; val.bv_val = (char *) Versionstr; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 3e90384d7e..1abab8b82a 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -176,9 +176,12 @@ char * dn_normalize_case LDAP_P(( char *dn )); char * dn_parent LDAP_P(( Backend *be, char *dn )); char * dn_rdn LDAP_P(( Backend *be, char *dn )); int dn_issuffix LDAP_P(( char *dn, char *suffix )); +#ifdef DNS_DN int dn_type LDAP_P(( char *dn )); +#endif char * str2upper LDAP_P(( char *str )); char * str2lower LDAP_P(( char *str )); +int rdn_validate LDAP_P(( const char* str )); char * rdn_attr_value LDAP_P(( char * rdn )); char * rdn_attr_type LDAP_P(( char * rdn )); void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn, diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index 25d5f7ddbf..700b4bd489 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -32,7 +32,8 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) e->e_attrs = NULL; e->e_dn = ch_strdup( LDAP_ROOT_DSE ); - e->e_ndn = dn_normalize_case( ch_strdup( LDAP_ROOT_DSE )); + e->e_ndn = ch_strdup( LDAP_ROOT_DSE ); + (void) dn_normalize_case( e->e_ndn ); e->e_private = NULL; for ( i = 0; i < nbackends; i++ ) { diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index e2e2294d56..ec67cc3905 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -1109,7 +1109,8 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) e->e_attrs = NULL; e->e_dn = ch_strdup( SLAPD_SCHEMA_DN ); - e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_SCHEMA_DN )); + e->e_ndn = ch_strdup( SLAPD_SCHEMA_DN ); + (void) dn_normalize_case( e->e_ndn ); e->e_private = NULL; val.bv_val = ch_strdup( "top" ); diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 92a34841bf..ef38c6a591 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -105,7 +105,12 @@ do_search( goto return_results; } - (void) dn_normalize_case( base ); + if( dn_normalize_case( base ) == NULL ) { + send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid DN", NULL, NULL ); + rc = -1; + goto return_results; + } Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref ); Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit, diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index aa558c6373..625890574f 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -45,8 +45,10 @@ LDAP_BEGIN_DECL */ #define LDAP_MOD_SOFTADD 0x1000 +#ifdef DNS_DN #define DN_DNS 0 #define DN_X500 1 +#endif #define ON 1 #define OFF (-1) diff --git a/servers/slapd/tools/ldif2id2children-bdb2.c b/servers/slapd/tools/ldif2id2children-bdb2.c index 1aac3017ea..61113a3462 100644 --- a/servers/slapd/tools/ldif2id2children-bdb2.c +++ b/servers/slapd/tools/ldif2id2children-bdb2.c @@ -177,7 +177,8 @@ main( int argc, char **argv ) fprintf( stderr, "entry %ld has no dn\n", id ); } else { - key.dptr = dn_normalize_case( val ); + (void) dn_normalize_case( val ); + key.dptr = val; key.dsize = strlen( val ) + 1; data.dptr = (char *) &id; data.dsize = sizeof(ID); @@ -262,15 +263,15 @@ main( int argc, char **argv ) == NULL ) { pid = 0; } else { - key.dptr = - dn_normalize_case( dn ); + (void) dn_normalize_case( dn ); + key.dptr = dn; key.dsize = strlen( dn ) + 1; data = ldbm_fetch( db->dbc_db, key ); free( dn ); if ( data.dptr == NULL ) { - dn_normalize_case( val ); + (void) dn_normalize_case( val ); if ( ! be_issuffix( be, val ) ) { Debug( LDAP_DEBUG_PARSE, "no parent \"%s\" of \"%s\"\n", dn, val, 0 ); diff --git a/servers/slapd/tools/ldif2id2children.c b/servers/slapd/tools/ldif2id2children.c index 3f43bf66f9..6eb25ea473 100644 --- a/servers/slapd/tools/ldif2id2children.c +++ b/servers/slapd/tools/ldif2id2children.c @@ -179,7 +179,8 @@ main( int argc, char **argv ) fprintf( stderr, "entry %ld has no dn\n", id ); } else { - key.dptr = dn_normalize_case( val ); + (void) dn_normalize_case( val ); + key.dptr = val; key.dsize = strlen( val ) + 1; data.dptr = (char *) &id; data.dsize = sizeof(ID); @@ -264,15 +265,15 @@ main( int argc, char **argv ) == NULL ) { pid = 0; } else { - key.dptr = - dn_normalize_case( dn ); + (void) dn_normalize_case( dn ); + key.dptr = dn; key.dsize = strlen( dn ) + 1; data = ldbm_fetch( db->dbc_db, key ); free( dn ); if ( data.dptr == NULL ) { - dn_normalize_case( val ); + (void) dn_normalize_case( val ); if ( ! be_issuffix( be, val ) ) { Debug( LDAP_DEBUG_PARSE, "no parent \"%s\" of \"%s\"\n", dn, val, 0 ); -- 2.39.5