From 78c50664d6421cc5d0836bb03820680dc2cb7acf Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Mon, 26 Apr 2010 11:03:52 -0700 Subject: Update to New DN Format Fix Description: . adding slapi_dn_normalize_ext and its siblings to normalize/validate invalid DNs; deprecating slapi_dn_normalize and its siblings. (dn.c) . replacing slapi_dn_normalize with new corresponding functions. . normalizing hardcoded DNs (e.g., removing spaces around ',') . setting correct DN syntax to nsslapd-suffix, nsslapd-ldapiautodnsuffix, costemplatedn, nsslapd-changelogsuffix, nsBaseDN, nsBindDN . if nsslapd-dn-validate-strict is enabled, incoming DN is examined and rejected if it is invalid. Once approved, the DN is normalized. . fixing compiler warnings and typos. See also: http://directory.fedoraproject.org/wiki/Upgrade_to_New_DN_Format Related bugs: Bug 199923 - subtree search fails to find items under a db containing special characters Bug 567968 - subtree/user level password policy created using 389-ds-console doesn't work. Bug 570107 - The import of LDIFs with base-64 encoded DNs fails, modrdn with non-ASCII new rdn incorrect Bug 570962 - ns-inactivate.pl does not work Bug 572785 - DN syntax: old style of DN ="", is not correctly normalized Bug 573060 - DN normalizer: ESC HEX HEX is not normalized Bug 574167 - An escaped space at the end of the RDN value is not handled correctly --- ldap/servers/slapd/modrdn.c | 108 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 7 deletions(-) (limited to 'ldap/servers/slapd/modrdn.c') diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c index b70377a9..6951fb05 100644 --- a/ldap/servers/slapd/modrdn.c +++ b/ldap/servers/slapd/modrdn.c @@ -72,10 +72,13 @@ do_modrdn( Slapi_PBlock *pb ) { Slapi_Operation *operation; BerElement *ber; + char *rawdn = NULL, *rawnewsuperior = NULL; char *dn = NULL, *newsuperior = NULL; + char *rawnewrdn = NULL; char *newrdn = NULL; int err = 0, deloldrdn = 0; ber_len_t len = 0; + size_t dnlen = 0; LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 ); @@ -96,7 +99,7 @@ do_modrdn( Slapi_PBlock *pb ) * } */ - if ( ber_scanf( ber, "{aab", &dn, &newrdn, &deloldrdn ) + if ( ber_scanf( ber, "{aab", &rawdn, &rawnewrdn, &deloldrdn ) == LBER_ERROR ) { LDAPDebug( LDAP_DEBUG_ANY, "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n", @@ -109,25 +112,116 @@ do_modrdn( Slapi_PBlock *pb ) } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) { + /* This "len" is not used... */ if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) { LDAPDebug( LDAP_DEBUG_ANY, "got newSuperior in LDAPv2 modrdn op\n", 0, 0, 0 ); - op_shared_log_error_access (pb, "MODRDN", dn, "decoding error"); + op_shared_log_error_access (pb, "MODRDN", + rawdn?rawdn:"", "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "received newSuperior in LDAPv2 modrdn", 0, NULL ); + slapi_ch_free_string( &rawdn ); + slapi_ch_free_string( &rawnewrdn ); goto free_and_return; } - if ( ber_scanf( ber, "a", &newsuperior ) == LBER_ERROR ) { + if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) { LDAPDebug( LDAP_DEBUG_ANY, "ber_scanf failed (op=ModRDN; params=newSuperior)\n", 0, 0, 0 ); - op_shared_log_error_access (pb, "MODRDN", dn, "decoding error"); + op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "unable to decode newSuperior parameter", 0, NULL ); + slapi_ch_free_string( &rawdn ); + slapi_ch_free_string( &rawnewrdn ); goto free_and_return; } } + /* Check if we should be performing strict validation. */ + if (config_get_dn_validate_strict()) { + /* check that the dn is formatted correctly */ + err = slapi_dn_syntax_check(pb, rawdn, 1); + if (err) { /* syntax check failed */ + op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"", + "strict: invalid dn"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid dn", 0, NULL); + slapi_ch_free_string( &rawdn ); + slapi_ch_free_string( &rawnewrdn ); + slapi_ch_free_string( &rawnewsuperior ); + goto free_and_return; + } + /* check that the new rdn is formatted correctly */ + err = slapi_dn_syntax_check(pb, rawnewrdn, 1); + if (err) { /* syntax check failed */ + op_shared_log_error_access(pb, "MODRDN", rawnewrdn?rawnewrdn:"", + "strict: invalid new rdn"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid new rdn", 0, NULL); + slapi_ch_free_string( &rawdn ); + slapi_ch_free_string( &rawnewrdn ); + slapi_ch_free_string( &rawnewsuperior ); + goto free_and_return; + } + } + err = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen); + if (err < 0) { + op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"", "invalid dn"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid dn", 0, NULL); + slapi_ch_free_string( &rawdn ); + slapi_ch_free_string( &rawnewrdn ); + slapi_ch_free_string( &rawnewsuperior ); + goto free_and_return; + } else if (err > 0) { + slapi_ch_free((void **) &rawdn); + } else { /* err == 0; rawdn is passed in; not null terminated */ + *(dn + dnlen) = '\0'; + } + err = slapi_dn_normalize_ext(rawnewrdn, 0, &newrdn, &dnlen); + if (err < 0) { + op_shared_log_error_access(pb, "MODRDN", rawnewrdn?rawnewrdn:"", + "invalid new rdn"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid new rdn", 0, NULL); + slapi_ch_free_string( &rawnewrdn ); + slapi_ch_free_string( &rawnewsuperior ); + goto free_and_return; + } else if (err > 0) { + slapi_ch_free((void **) &rawnewrdn); + } else { /* err == 0; rawnewdn is passed in; not null terminated */ + *(newrdn + dnlen) = '\0'; + } + if (rawnewsuperior) { + if (config_get_dn_validate_strict()) { + /* check that the dn is formatted correctly */ + err = slapi_dn_syntax_check(pb, rawnewsuperior, 1); + if (err) { /* syntax check failed */ + op_shared_log_error_access(pb, "MODRDN", + rawnewsuperior?rawnewsuperior:"", + "strict: invalid new superior"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid new superior", 0, NULL); + slapi_ch_free_string( &rawnewsuperior ); + goto free_and_return; + } + } + err = slapi_dn_normalize_ext(rawnewsuperior, 0, &newsuperior, &dnlen); + if (err < 0) { + op_shared_log_error_access(pb, "MODRDN", + rawnewsuperior?rawnewsuperior:"", + "invalid new superior"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid new superior", 0, NULL); + slapi_ch_free_string( &rawnewsuperior); + goto free_and_return; + } else if (err > 0) { + slapi_ch_free((void **) &rawnewsuperior); + } else { /* err == 0; rawnewsuperior is passed in; not terminated */ + *(newsuperior + dnlen) = '\0'; + } + } + /* * in LDAPv3 there can be optional control extensions on * the end of an LDAPMessage. we need to read them in and @@ -153,9 +247,9 @@ do_modrdn( Slapi_PBlock *pb ) return; free_and_return: - slapi_ch_free((void **) &dn ); - slapi_ch_free((void **) &newrdn ); - slapi_ch_free((void **) &newsuperior ); + slapi_ch_free_string( &dn ); + slapi_ch_free_string( &newrdn ); + slapi_ch_free_string( &newsuperior ); return; } -- cgit