ldap/servers/plugins/acl/acllas.c | 17
ldap/servers/plugins/memberof/memberof.c | 24 -
ldap/servers/plugins/referint/referint.c | 5
ldap/servers/plugins/replication/urp.c | 3
ldap/servers/plugins/replication/windows_protocol_util.c | 90 ++--
ldap/servers/slapd/attr.c | 58 +--
ldap/servers/slapd/filter.c | 51 +-
ldap/servers/slapd/ldaputil.c | 145 +++----
ldap/servers/slapd/libslapd.def | 4
ldap/servers/slapd/main.c | 8
ldap/servers/slapd/mapping_tree.c | 14
ldap/servers/slapd/plugin.c | 2
ldap/servers/slapd/slapi-plugin.h | 15
ldap/servers/slapd/slapi-private.h | 1
ldap/servers/slapd/util.c | 278 ++++++++++++++-
15 files changed, 500 insertions(+), 215 deletions(-)
New commits:
commit 3cf9a521fa43183c657a5dca507dec3a4379e383
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Wed Aug 1 12:40:31 2012 -0400
Ticket 328 - make sure all internal search filters are properly escaped
Bug Description: Not all internal search fitlers are properly escaped.
Fix Description: Created a new sprintf type function, and a filter value escape
function.
The sprintf function(slapi_filter_sprintf) varies from sprintf as
you pass
a description argument before the value you want to
escape/normalize:
ESC_NEXT_VAL - escape the next argument
NORM_NEXT_VAL - normalize the next argument
ESC_AND_NORM_NEXT_VAL - escape and normalize the next argument
In order to correctly normalize the value, the function also parses
out the attribute
so we can get the syntax plugin normalization function.
As a side effect you must add an additional string format character
for the description
arg(%s):
sprintf(buf,"cn=%s", value);
escaped_val = slapi_filter_sprintf("cn=%s%s",
ESC_NEXT_VAL, value);
Also did some code cleanup.
https://fedorahosted.org/389/ticket/328
reviewed by: Noriko(Thanks!)
diff --git a/ldap/servers/plugins/acl/acllas.c b/ldap/servers/plugins/acl/acllas.c
index cc556c4..5bcb482 100644
--- a/ldap/servers/plugins/acl/acllas.c
+++ b/ldap/servers/plugins/acl/acllas.c
@@ -2896,7 +2896,6 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
** client is a member of.
*/
if (enumerate_groups) {
- char filter_str[BUFSIZ];
char *attrs[3];
struct eval_info info = {0};
char *curMemberDn;
@@ -2934,23 +2933,15 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
curMemberDn = n_clientdn;
while (!Done) {
- char *filter_str_ptr = &filter_str[0];
- char *new_filter_str = NULL;
- int lenf = strlen(curMemberDn)<<1;
-
- if (lenf > (BUFSIZ - 28)) { /* 28 for "(|(uniquemember=%s)(member=%s))"
*/
- new_filter_str = slapi_ch_malloc(lenf + 28);
- filter_str_ptr = new_filter_str;
- }
+ char *filter_str_ptr;
/*
** Search the db for groups that the client is a member of.
** Once found cache it. cache only unique groups.
*/
tt = info.lu_idx;
- sprintf (filter_str_ptr,"(|(uniquemember=%s)(member=%s))",
- curMemberDn, curMemberDn);
-
+ filter_str_ptr =
slapi_filter_sprintf("(|(uniquemember=%s%s)(member=%s%s))",
+ ESC_AND_NORM_NEXT_VAL, curMemberDn, ESC_AND_NORM_NEXT_VAL ,curMemberDn);
/* Use new search internal API */
{
Slapi_PBlock *aPb = slapi_pblock_new ();
@@ -2976,7 +2967,7 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
slapi_pblock_destroy (aPb);
}
- if (new_filter_str) slapi_ch_free((void **) &new_filter_str);
+ slapi_ch_free_string(&filter_str_ptr);
if (tt == info.lu_idx) {
slapi_log_error( SLAPI_LOG_ACL, plugin_name, "currDn:(%s) \n\tNO MEMBER
ADDED\n",
diff --git a/ldap/servers/plugins/memberof/memberof.c
b/ldap/servers/plugins/memberof/memberof.c
index a2fdbd9..a69dd16 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -520,12 +520,14 @@ int memberof_call_foreach_dn(Slapi_PBlock *pb, Slapi_DN *sdn,
Slapi_PBlock *search_pb = NULL;
Slapi_DN *base_sdn = NULL;
Slapi_Backend *be = NULL;
+ char *escaped_filter_val;
char *filter_str = NULL;
char *cookie = NULL;
int all_backends = memberof_config_get_all_backends();
int types_name_len = 0;
int num_types = 0;
int dn_len = slapi_sdn_get_ndn_len(sdn);
+ int free_it = 0;
int rc = 0;
int i = 0;
@@ -537,7 +539,15 @@ int memberof_call_foreach_dn(Slapi_PBlock *pb, Slapi_DN *sdn,
types_name_len += strlen(types[num_types]);
}
- /* Build the search filter. */
+ /* Escape the dn, and build the search filter. */
+ escaped_filter_val = slapi_escape_filter_value((char *)slapi_sdn_get_dn(sdn), dn_len);
+ if(escaped_filter_val){
+ dn_len = strlen(escaped_filter_val);
+ free_it = 1;
+ } else {
+ escaped_filter_val = (char *)slapi_sdn_get_dn(sdn);
+ }
+
if (num_types > 1)
{
int bytes_out = 0;
@@ -553,7 +563,7 @@ int memberof_call_foreach_dn(Slapi_PBlock *pb, Slapi_DN *sdn,
for (i = 0; types[i]; i++)
{
bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
- "(%s=%s)", types[i], slapi_sdn_get_ndn(sdn));
+ "(%s=%s)", types[i], escaped_filter_val);
}
/* Add end of filter. */
@@ -561,10 +571,12 @@ int memberof_call_foreach_dn(Slapi_PBlock *pb, Slapi_DN *sdn,
}
else if (num_types == 1)
{
- filter_str =
- slapi_ch_smprintf("(%s=%s)", types[0], slapi_sdn_get_ndn(sdn));
+ filter_str = slapi_ch_smprintf("(%s=%s)", types[0], escaped_filter_val);
}
+ if(free_it)
+ slapi_ch_free_string(&escaped_filter_val);
+
if(filter_str == NULL){
return rc;
}
@@ -1131,12 +1143,12 @@ memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig
*config,
Slapi_PBlock *search_pb = slapi_pblock_new();
Slapi_DN *base_sdn = 0;
Slapi_Backend *be = 0;
- char *filter_str = 0;
+ char *filter_str;
char *cookie = NULL;
int n_entries = 0;
int all_backends = config->allBackends;
- filter_str = slapi_ch_smprintf("(%s=%s)", config->memberof_attr, op_to);
+ filter_str = slapi_filter_sprintf("(%s=%s%s)", config->memberof_attr,
ESC_NEXT_VAL, op_to);
be = slapi_get_first_backend(&cookie);
while(be){
/*
diff --git a/ldap/servers/plugins/referint/referint.c
b/ldap/servers/plugins/referint/referint.c
index 3342634..0d381fe 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -684,7 +684,6 @@ update_integrity(char **argv, Slapi_DN *origSDN,
char *attrName = NULL;
char *filter = NULL;
char *attrs[2];
- size_t len = slapi_sdn_get_ndn_len(origSDN);
int search_result;
int nval = 0;
int i, j;
@@ -709,9 +708,7 @@ update_integrity(char **argv, Slapi_DN *origSDN,
search_base = slapi_sdn_get_dn( sdn );
for(i = 3; argv[i] != NULL; i++){
- char buf[BUFSIZ];
- filter = slapi_ch_smprintf("(%s=*%s)", argv[i],
- escape_filter_value(origDN, len, buf));
+ filter = slapi_filter_sprintf("(%s=*%s%s)", argv[i], ESC_NEXT_VAL,
origDN);
if ( filter ) {
/* Need only the current attribute and its subtypes */
attrs[0] = argv[i];
diff --git a/ldap/servers/plugins/replication/urp.c
b/ldap/servers/plugins/replication/urp.c
index 1d8799a..7608382 100644
--- a/ldap/servers/plugins/replication/urp.c
+++ b/ldap/servers/plugins/replication/urp.c
@@ -1082,7 +1082,8 @@ urp_get_min_naming_conflict_entry ( Slapi_PBlock *pb, char
*sessionid, CSN *opcs
slapi_log_error ( SLAPI_LOG_REPL, sessionid,
"Enter urp_get_min_naming_conflict_entry for %s\n", basedn);
- filter = PR_smprintf("(%s=%s %s)", ATTR_NSDS5_REPLCONFLICT,
REASON_ANNOTATE_DN, basedn);
+ filter = slapi_filter_sprintf("(%s=%s %s%s)", ATTR_NSDS5_REPLCONFLICT,
REASON_ANNOTATE_DN,
+ ESC_NEXT_VAL, basedn);
/* server_ctrls will be freed when newpb is destroyed */
server_ctrls = (LDAPControl **)slapi_ch_calloc (2, sizeof (LDAPControl *));
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c
b/ldap/servers/plugins/replication/windows_protocol_util.c
index 3970353..fb10fb0 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -2913,14 +2913,9 @@ find_entry_by_attr_value_remote(const char *attribute, const char
*value, Slapi_
char *filter = NULL;
const char *searchbase = NULL;
Slapi_Entry *found_entry = NULL;
- char *filter_escaped_value = NULL;
- size_t vallen = 0;
- vallen = value ? strlen(value) : 0;
- filter_escaped_value = slapi_ch_calloc(sizeof(char), vallen*3+1);
/* should not have to escape attribute names */
- filter = PR_smprintf("(%s=%s)",attribute,escape_filter_value(value, vallen,
filter_escaped_value));
- slapi_ch_free_string(&filter_escaped_value);
+ filter = slapi_filter_sprintf("(%s=%s%s)",attribute, ESC_NEXT_VAL, value);
searchbase = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
cres = windows_search_entry(prp->conn, (char*)searchbase, filter, &found_entry);
if (cres)
@@ -2935,7 +2930,7 @@ find_entry_by_attr_value_remote(const char *attribute, const char
*value, Slapi_
}
if (filter)
{
- PR_smprintf_free(filter);
+ slapi_ch_free_string(&filter);
filter = NULL;
}
return retval;
@@ -3035,33 +3030,28 @@ find_entry_by_attr_value(const char *attribute, const char *value,
Slapi_Entry *
{
Slapi_PBlock *pb = slapi_pblock_new();
Slapi_Entry **entries = NULL, **ep = NULL;
- Slapi_Entry *entry_found = NULL;
+ Slapi_Entry *entry_found = NULL;
+ LDAPControl **server_controls = NULL;
+ const char *subtree_dn = NULL;
+ char *subtree_dn_copy = NULL;
+ char **attrs = NULL;
char *query = NULL;
- int found_or_not = ENTRY_NOTFOUND;
- int rval = 0;
- const char *subtree_dn = NULL;
- int not_unique = 0;
- char *subtree_dn_copy = NULL;
- int scope = LDAP_SCOPE_SUBTREE;
- char **attrs = NULL;
- LDAPControl **server_controls = NULL;
- char *filter_escaped_value = NULL;
- size_t vallen = 0;
+ int found_or_not = ENTRY_NOTFOUND;
+ int scope = LDAP_SCOPE_SUBTREE;
+ int not_unique = 0;
+ int rval = 0;
if (pb == NULL)
goto done;
- vallen = value ? strlen(value) : 0;
- filter_escaped_value = slapi_ch_calloc(sizeof(char), vallen*3+1);
/* should not have to escape attribute names */
- query = slapi_ch_smprintf("(%s=%s)", attribute, escape_filter_value(value,
vallen, filter_escaped_value));
- slapi_ch_free_string(&filter_escaped_value);
+ query = slapi_filter_sprintf("(%s=%s%s)", attribute, ESC_NEXT_VAL, value);
if (query == NULL)
- goto done;
+ goto done;
- subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
- subtree_dn_copy = slapi_ch_strdup(subtree_dn);
+ subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+ subtree_dn_copy = slapi_ch_strdup(subtree_dn);
winsync_plugin_call_pre_ds_search_entry_cb(ra, NULL, &subtree_dn_copy,
&scope, &query,
&attrs, &server_controls);
@@ -3079,35 +3069,35 @@ find_entry_by_attr_value(const char *attribute, const char *value,
Slapi_Entry *
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
if (rval != LDAP_SUCCESS)
- {
- goto done;
- }
+ {
+ goto done;
+ }
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if ((entries == NULL) || (entries[0] == NULL))
- {
- goto done;
- }
- entry_found = entries[0];
- for (ep = entries; *ep; ep++) {
- if (not_unique)
- {
- found_or_not = ENTRY_NOT_UNIQUE;
- }
- not_unique = 1;
- }
+ {
+ goto done;
+ }
+ entry_found = entries[0];
+ for (ep = entries; *ep; ep++) {
+ if (not_unique)
+ {
+ found_or_not = ENTRY_NOT_UNIQUE;
+ }
+ not_unique = 1;
+ }
done:
- if (entry_found && (found_or_not != ENTRY_NOT_UNIQUE))
- {
- found_or_not = 0;
- *e = slapi_entry_dup(entry_found);
- }
- if (pb)
- {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- }
- return found_or_not;
+ if (entry_found && (found_or_not != ENTRY_NOT_UNIQUE))
+ {
+ found_or_not = 0;
+ *e = slapi_entry_dup(entry_found);
+ }
+ if (pb)
+ {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ }
+ return found_or_not;
}
static int
diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c
index 7fb613c..73892bf 100644
--- a/ldap/servers/slapd/attr.c
+++ b/ldap/servers/slapd/attr.c
@@ -574,36 +574,36 @@ slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1,
const struct
int
slapi_attr_value_cmp_ext(const Slapi_Attr *a, Slapi_Value *v1, Slapi_Value *v2)
{
- int retVal;
- const struct berval *bv2 = slapi_value_get_berval(v2);
-
- if ( a->a_flags & SLAPI_ATTR_FLAG_CMP_BITBYBIT )
- {
- const struct berval *bv1 = slapi_value_get_berval(v1);
- return slapi_attr_value_cmp(a, bv1, bv2);
- }
- else
- {
- Slapi_Attr a2;
- struct ava ava;
- Slapi_Value *cvals[2];
- unsigned long v2_flags = v2->v_flags;
-
- a2 = *a;
- cvals[0] = v1;
- cvals[1] = NULL;
- a2.a_present_values.va = cvals; /* JCM - PUKE */
+ int retVal;
+ const struct berval *bv2 = slapi_value_get_berval(v2);
- ava.ava_type = a->a_type;
- ava.ava_value = *bv2;
- if (v2_flags) {
- ava.ava_private = &v2_flags;
- } else {
- ava.ava_private = NULL;
- }
- retVal = plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava);
- }
- return retVal;
+ if ( a->a_flags & SLAPI_ATTR_FLAG_CMP_BITBYBIT )
+ {
+ const struct berval *bv1 = slapi_value_get_berval(v1);
+ return slapi_attr_value_cmp(a, bv1, bv2);
+ }
+ else
+ {
+ Slapi_Attr a2;
+ struct ava ava;
+ Slapi_Value *cvals[2];
+ unsigned long v2_flags = v2->v_flags;
+
+ a2 = *a;
+ cvals[0] = v1;
+ cvals[1] = NULL;
+ a2.a_present_values.va = cvals; /* JCM - PUKE */
+
+ ava.ava_type = a->a_type;
+ ava.ava_value = *bv2;
+ if (v2_flags) {
+ ava.ava_private = &v2_flags;
+ } else {
+ ava.ava_private = NULL;
+ }
+ retVal = plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY,
&ava);
+ }
+ return retVal;
}
/*
diff --git a/ldap/servers/slapd/filter.c b/ldap/servers/slapd/filter.c
index ae87e5c..65e9de4 100644
--- a/ldap/servers/slapd/filter.c
+++ b/ldap/servers/slapd/filter.c
@@ -124,11 +124,11 @@ get_filter( Connection *conn, BerElement *ber, int scope,
}
-#define FILTER_EQ_FMT "(%s=%s)"
-#define FILTER_GE_FMT "(%s>=%s)"
-#define FILTER_LE_FMT "(%s<=%s)"
-#define FILTER_APROX_FMT "(%s~=%s)"
-#define FILTER_EXTENDED_FMT "(%s%s%s%s:=%s)"
+#define FILTER_EQ_FMT "(%s=%s%s)"
+#define FILTER_GE_FMT "(%s>=%s%s)"
+#define FILTER_LE_FMT "(%s<=%s%s)"
+#define FILTER_APROX_FMT "(%s~=%s%s)"
+#define FILTER_EXTENDED_FMT "(%s%s%s%s:=%s%s)"
#define FILTER_EQ_LEN 4
#define FILTER_GE_LEN 5
#define FILTER_LE_LEN 5
@@ -140,16 +140,14 @@ get_filter( Connection *conn, BerElement *ber, int scope,
static char *
filter_escape_filter_value_extended(struct slapi_filter *f)
{
- char ebuf[BUFSIZ], *ptr;
- const char *estr;
+ char *ptr;
- estr = escape_filter_value( f->f_mr_value.bv_val, f->f_mr_value.bv_len, ebuf
);
- ptr = slapi_ch_smprintf(FILTER_EXTENDED_FMT,
+ ptr = slapi_filter_sprintf(FILTER_EXTENDED_FMT,
f->f_mr_type ? f->f_mr_type : "",
f->f_mr_dnAttrs ? ":dn" : "",
f->f_mr_oid ? ":" : "",
f->f_mr_oid ? f->f_mr_oid : "",
- estr );
+ ESC_NEXT_VAL, f->f_mr_value.bv_val);
return ptr;
}
@@ -158,12 +156,11 @@ filter_escape_filter_value_extended(struct slapi_filter *f)
static char *
filter_escape_filter_value(struct slapi_filter *f, const char *fmt, size_t len)
{
- char ebuf[BUFSIZ], *ptr;
- const char *estr;
+ char *ptr;
+
+ filter_compute_hash(f);
+ ptr = slapi_filter_sprintf(fmt, f->f_avtype, ESC_NEXT_VAL, f->f_avvalue.bv_val
);
- estr = escape_filter_value( f->f_avvalue.bv_val, f->f_avvalue.bv_len, ebuf );
- filter_compute_hash(f);
- ptr = slapi_ch_smprintf(fmt, f->f_avtype, estr );
return ptr;
}
@@ -474,8 +471,7 @@ get_substring_filter(
{
ber_tag_t tag, rc;
ber_len_t len = -1;
- char *val, *last, *type = NULL;
- char ebuf[BUFSIZ];
+ char *val, *eval, *last, *type = NULL;
LDAPDebug( LDAP_DEBUG_FILTER, "=> get_substring_filter\n", 0, 0, 0 );
@@ -516,8 +512,11 @@ get_substring_filter(
return( LDAP_PROTOCOL_ERROR );
}
f->f_sub_initial = val;
- /* jcm: Had to cast away a const */
- val = (char*)escape_filter_value( val, -1, ebuf );
+ eval = (char*)slapi_escape_filter_value( val, -1);
+ if(eval){
+ slapi_ch_free_string(&val);
+ val = eval;
+ }
*fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 1 );
strcat( *fstr, val );
@@ -526,8 +525,11 @@ get_substring_filter(
case LDAP_SUBSTRING_ANY:
LDAPDebug( LDAP_DEBUG_FILTER, " ANY\n", 0, 0, 0 );
charray_add( &f->f_sub_any, val );
- /* jcm: Had to cast away a const */
- val = (char*)escape_filter_value( val, -1, ebuf );
+ eval = (char*)slapi_escape_filter_value( val, -1);
+ if(eval){
+ slapi_ch_free_string(&val);
+ val = eval;
+ }
*fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 2 );
strcat( *fstr, "*" );
@@ -540,8 +542,11 @@ get_substring_filter(
return( LDAP_PROTOCOL_ERROR );
}
f->f_sub_final = val;
- /* jcm: Had to cast away a const */
- val = (char*)escape_filter_value( val, -1, ebuf );
+ eval = (char*)slapi_escape_filter_value( val, -1);
+ if(eval){
+ slapi_ch_free_string(&val);
+ val = eval;
+ }
*fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 2 );
strcat( *fstr, "*" );
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index aaca1af..7d77644 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -304,53 +304,56 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int
require_dn, int *
replace all but the last colon with %3A
Go to the 3rd '/' or to the end of the string (convert only the host:port
part) */
if (url) {
- char *p = strstr(url, "://");
- if (p) {
- int foundspace = 0;
- int coloncount = 0;
- char *lastcolon = NULL;
- p += 3;
- for (; *p && (*p != '/'); p++) {
- if (*p == ' ') {
- foundspace = 1;
- }
- if (*p == ':') {
- coloncount++;
- lastcolon = p;
- }
- }
- if (foundspace) {
- char *src = NULL, *dest = NULL;
- /* have to convert url */
- /* len * 3 is way too much, but acceptable */
- urlescaped = slapi_ch_calloc(strlen(url) * 3, sizeof(char));
- dest = urlescaped;
- /* copy the scheme */
- src = strstr(url, "://");
- src += 3;
- memcpy(dest, url, src-url);
- dest += (src-url);
- /* we have to convert all spaces to %20 - we have to convert
- all colons except the last one to %3A */
- for (; *src; ++src) {
- if (src < p) {
- if (*src == ' ') {
- memcpy(dest, "%20", 3);
- dest += 3;
- } else if ((coloncount > 1) && (*src == ':') && (src !=
lastcolon)) {
- memcpy(dest, "%3A", 3);
- dest += 3;
- } else {
- *dest++ = *src;
- }
- } else {
- *dest++ = *src;
- }
- }
- *dest = '\0';
- url_to_use = urlescaped;
- }
- }
+ char *p = strstr(url, "://");
+ if (p) {
+ int foundspace = 0;
+ int coloncount = 0;
+ char *lastcolon = NULL;
+
+ p += 3;
+ for (; *p && (*p != '/'); p++) {
+ if (*p == ' ') {
+ foundspace = 1;
+ }
+ if (*p == ':') {
+ coloncount++;
+ lastcolon = p;
+ }
+ }
+ if (foundspace) {
+ char *src = NULL, *dest = NULL;
+
+ /* have to convert url, len * 3 is way too much, but acceptable */
+ urlescaped = slapi_ch_calloc(strlen(url) * 3, sizeof(char));
+ dest = urlescaped;
+ /* copy the scheme */
+ src = strstr(url, "://");
+ src += 3;
+ memcpy(dest, url, src-url);
+ dest += (src-url);
+ /*
+ * we have to convert all spaces to %20 - we have to convert
+ * all colons except the last one to %3A
+ */
+ for (; *src; ++src) {
+ if (src < p) {
+ if (*src == ' ') {
+ memcpy(dest, "%20", 3);
+ dest += 3;
+ } else if ((coloncount > 1) && (*src == ':')
&& (src != lastcolon)) {
+ memcpy(dest, "%3A", 3);
+ dest += 3;
+ } else {
+ *dest++ = *src;
+ }
+ } else {
+ *dest++ = *src;
+ }
+ }
+ *dest = '\0';
+ url_to_use = urlescaped;
+ }
+ }
}
#endif
@@ -388,30 +391,30 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int
require_dn, int *
#if defined(USE_OPENLDAP)
if (urlescaped && (*ludpp) && (*ludpp)->lud_host) {
- /* have to unescape lud_host - can unescape in place */
- char *p = strstr((*ludpp)->lud_host, "://");
- if (p) {
- char *dest = NULL;
- p += 3;
- dest = p;
- /* up to the first '/', unescape the host */
- for (; *p && (*p != '/'); p++) {
- if (!strncmp(p, "%20", 3)) {
- *dest++ = ' ';
- p += 2;
- } else if (!strncmp(p, "%3A", 3)) {
- *dest++ = ':';
- p += 2;
- } else {
- *dest++ = *p;
- }
- }
- /* just copy the remainder of the host, if any */
- while (*p) {
- *dest++ = *p++;
- }
- *dest = '\0';
- }
+ /* have to unescape lud_host - can unescape in place */
+ char *p = strstr((*ludpp)->lud_host, "://");
+ if (p) {
+ char *dest = NULL;
+ p += 3;
+ dest = p;
+ /* up to the first '/', unescape the host */
+ for (; *p && (*p != '/'); p++) {
+ if (!strncmp(p, "%20", 3)) {
+ *dest++ = ' ';
+ p += 2;
+ } else if (!strncmp(p, "%3A", 3)) {
+ *dest++ = ':';
+ p += 2;
+ } else {
+ *dest++ = *p;
+ }
+ }
+ /* just copy the remainder of the host, if any */
+ while (*p) {
+ *dest++ = *p++;
+ }
+ *dest = '\0';
+ }
}
slapi_ch_free_string(&urlescaped);
#endif
diff --git a/ldap/servers/slapd/libslapd.def b/ldap/servers/slapd/libslapd.def
index c5fd242..70a2993 100644
--- a/ldap/servers/slapd/libslapd.def
+++ b/ldap/servers/slapd/libslapd.def
@@ -1097,8 +1097,8 @@ EXPORTS
slapi_mtn_get_dn @1098
dl_add_index @1099
dl_replace @1100
- send_referrals_from_entry @1101
- escape_filter_value @1102
+ send_referrals_from_entry @1101
+ slapi_escape_filter_value @1102
slapd_pk11_destroyContext @1103
secoid_destroyAlgorithmID @1104
op_shared_is_allowed_attr @1105
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 7b15249..d60913f 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1929,7 +1929,8 @@ lookup_instance_name_by_suffix(char *suffix,
goto done;
if (isexact) {
- query =
slapi_ch_smprintf("(&(objectclass=nsmappingtree)(|(cn=\"%s\")(cn=%s)))",
suffix, suffix);
+ query =
slapi_filter_sprintf("(&(objectclass=nsmappingtree)(|(cn=\"%s%s\")(cn=%s%s)))",
+ ESC_NEXT_VAL, suffix, ESC_NEXT_VAL, suffix);
if (query == NULL)
goto done;
@@ -1951,7 +1952,8 @@ lookup_instance_name_by_suffix(char *suffix,
} else {
char *suffixp = suffix;
while (NULL != suffixp && strlen(suffixp) > 0) {
- query =
slapi_ch_smprintf("(&(objectclass=nsmappingtree)(|(cn=*%s\")(cn=*%s)))",
suffixp, suffixp);
+ query =
slapi_filter_sprintf("(&(objectclass=nsmappingtree)(|(cn=*%s%s\")(cn=*%s%s)))",
+ ESC_NEXT_VAL, suffixp, ESC_NEXT_VAL, suffixp);
if (query == NULL)
goto done;
/* Note: This DN is no need to be normalized. */
@@ -2036,7 +2038,7 @@ static struct slapdplugin *lookup_plugin_by_instance_name(const char
*name)
if (pb == NULL)
return NULL;
- query = slapi_ch_smprintf("(&(cn=%s)(objectclass=nsBackendInstance))",
name);
+ query =
slapi_filter_sprintf("(&(cn=%s%s)(objectclass=nsBackendInstance))",
ESC_AND_NORM_NEXT_VAL, name);
if (query == NULL) {
slapi_pblock_destroy(pb);
return NULL;
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index e8e414f..dad5940 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -908,9 +908,9 @@ static int
mapping_tree_node_get_children(mapping_tree_node *target, int is_root)
{
Slapi_PBlock *pb;
- char * filter = NULL;
- int res;
Slapi_Entry **entries = NULL;
+ char *filter = NULL;
+ int res;
int x;
int result = 0;
@@ -923,11 +923,11 @@ mapping_tree_node_get_children(mapping_tree_node *target, int
is_root)
filter =
slapi_ch_smprintf("(&(objectclass=nsMappingTree)(!(%s=*)))",
MAPPING_TREE_PARENT_ATTRIBUTE);
} else {
- filter =
slapi_ch_smprintf("(&(objectclass=nsMappingTree)(|(%s=\"%s\")(%s=%s)))",
- MAPPING_TREE_PARENT_ATTRIBUTE,
- slapi_sdn_get_dn(target->mtn_subtree),
- MAPPING_TREE_PARENT_ATTRIBUTE,
- slapi_sdn_get_dn(target->mtn_subtree));
+ const char *filter_value = slapi_sdn_get_dn(target->mtn_subtree);
+
+ filter =
slapi_filter_sprintf("(&(objectclass=nsMappingTree)(|(%s=\"%s%s\")(%s=%s%s)))",
+ MAPPING_TREE_PARENT_ATTRIBUTE, ESC_NEXT_VAL, filter_value,
+ MAPPING_TREE_PARENT_ATTRIBUTE, ESC_NEXT_VAL, filter_value );
}
slapi_search_internal_set_pb(pb, MAPPING_TREE_BASE_DN, LDAP_SCOPE_ONELEVEL,
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 436cc02..f90bd0d 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -3024,7 +3024,7 @@ plugin_enabled(const char *plugin_name, void *identity)
char *filter = NULL;
int rc = 0; /* disabled, by default */
- filter = slapi_ch_smprintf("cn=%s", plugin_name);
+ filter = slapi_filter_sprintf("cn=%s%s", ESC_NEXT_VAL, plugin_name);
search_pb = slapi_pblock_new();
slapi_search_internal_set_pb(search_pb, PLUGIN_BASE_DN, LDAP_SCOPE_ONELEVEL,
filter, NULL, 0, NULL, NULL, identity, 0);
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 192d663..3fd8aed 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -3593,6 +3593,21 @@ void slapi_rand_array(void *randx, size_t len);
*/
int slapi_rand();
+/**
+ * Escape special characters in a search filter value
+ *
+ * \param filter_str A ldap search filter value (cn=VALUE_TO_BE_ESCAPED)
+ * \param len length of the search filter value. -1 indicates the string is null
terminated
+ * \param buf the buffer to store the escaped filter value string
+ * \return the escaped filter value string
+ */
+char* slapi_escape_filter_value(char* filter_str, int len);
+
+#define ESC_NEXT_VAL "__ESC__NEXT__VAL__"
+#define NORM_NEXT_VAL "__NORM__NEXT__VAL__"
+#define ESC_AND_NORM_NEXT_VAL "__ESC__AND__NORM__NEXT__VAL__"
+
+char* slapi_filter_sprintf(const char *fmt, ...);
/*
* attribute routines
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 68c2329..a57b453 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1143,7 +1143,6 @@ char* slapd_get_tmp_dir( void );
#include <stdio.h> /* GGOODREPL - For BUFSIZ, below, gak */
const char* escape_string (const char* str, char buf[BUFSIZ]);
const char* escape_string_with_punctuation(const char* str, char buf[BUFSIZ]);
-const char* escape_filter_value(const char* str, int len, char buf[BUFSIZ]);
void strcpy_unescape_value( char *d, const char *s );
char *slapi_berval_get_string_copy(const struct berval *bval);
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index 48a452f..c3f3593 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -72,6 +72,10 @@
#define _CSEP '/'
#endif
+/* slapi_filter_sprintf macros */
+#define ATTRSIZE 256 /* size allowed for an attr name */
+#define FILTER_BUF 128 /* initial buffer size for attr value */
+#define BUF_INCR 16 /* the amount to increase the FILTER_BUF once it fills up */
static int special_np(unsigned char c)
{
@@ -95,6 +99,7 @@ static int special_np_and_punct(unsigned char c)
return UTIL_ESCAPE_NONE;
}
+#ifndef USE_OPENLDAP
static int special_filter(unsigned char c)
{
/*
@@ -110,6 +115,27 @@ static int special_filter(unsigned char c)
c == '\\' ||
c == '"') ? UTIL_ESCAPE_HEX : UTIL_ESCAPE_NONE;
}
+#endif
+
+/*
+ * Used by filter_stuff_func to help extract an attribute so we know
+ * how to normalize the value.
+ */
+static int
+special_attr_char(unsigned char c)
+{
+ return (c < 32 ||
+ c > 126 ||
+ c == '*' ||
+ c == '|' ||
+ c == '&' ||
+ c == '!' ||
+ c == '(' ||
+ c == ')' ||
+ c == '\\' ||
+ c == '=' ||
+ c == '"');
+}
static const char*
do_escape_string (
@@ -180,7 +206,7 @@ do_escape_string (
*bufNext = '\0';
return buf;
}
- }
+ }
return str;
}
@@ -206,10 +232,254 @@ escape_string_with_punctuation(const char* str, char buf[BUFSIZ])
return do_escape_string(str,-1,buf,special_np_and_punct);
}
-const char*
-escape_filter_value(const char* str, int len, char buf[BUFSIZ])
+#define ESCAPE_FILTER 1
+#define NORM_FILTER 2
+
+struct filter_ctx {
+ char *buf;
+ char attr[ATTRSIZE];
+ int attr_position;
+ int attr_found;
+ int buf_size;
+ int buf_len;
+ int next_arg_needs_esc_norm;
+ int skip_escape;
+};
+
+/*
+ * This function is called by slapi_filter_sprintf to escape/normalize certain values
+ */
+static PRIntn
+filter_stuff_func(void *arg, const char *val, PRUint32 slen)
{
- return do_escape_string(str,len,buf,special_filter);
+ struct filter_ctx *ctx = (struct filter_ctx *)arg;
+ struct berval escaped_filter;
+ struct berval raw_filter;
+ char *buf = (char *)val;
+ int extra_space;
+ int filter_len = slen;
+ int free_buf = 0;
+
+ /* look at val - if val is one of our special keywords, and make a note of it for the
next pass */
+ if (strcmp(val, ESC_NEXT_VAL) == 0){
+ ctx->next_arg_needs_esc_norm |= ESCAPE_FILTER;
+ return 0;
+ }
+ if (strcmp(val, NORM_NEXT_VAL) == 0){
+ ctx->next_arg_needs_esc_norm |= NORM_FILTER;
+ return 0;
+ }
+ if (strcmp(val, ESC_AND_NORM_NEXT_VAL) == 0){
+ ctx->next_arg_needs_esc_norm = NORM_FILTER | ESCAPE_FILTER;
+ return 0;
+ }
+ /*
+ * Start collecting the attribute name so we can use the correct
+ * syntax normalization func.
+ */
+ if(ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)){
+ if(ctx->attr[0] == '\0'){
+ if(strstr(val,"=")){
+ /* we have an attr we need to record */
+ if(!special_attr_char(val[0])){
+ memcpy(ctx->attr, val, 1);
+ ctx->attr_position++;
+ }
+ } else {
+ /*
+ * We have passed in an attribute as a arg - so we can just set the
+ * attr with val. The next pass should be '=', otherwise we
will
+ * reset it.
+ */
+ memcpy(ctx->attr, val, slen);
+ ctx->attr_position = slen;
+ }
+ } else {
+ if(val[0] == '='){ /* hit the end of the attribute name */
+ ctx->attr_found = 1;
+ } else {
+ if(special_attr_char(val[0])){
+ /* this is not an attribute, we should not be collecting this, reset
everything */
+ memset(ctx->attr, '\0', ATTRSIZE);
+ ctx->attr_position = 0;
+ } else {
+ memcpy(ctx->attr + ctx->attr_position, val, 1);
+ ctx->attr_position++;
+ }
+ }
+ }
+ }
+
+ if (ctx->next_arg_needs_esc_norm && !ctx->skip_escape){
+ /*
+ * Normalize the filter value first
+ */
+ if(ctx->next_arg_needs_esc_norm & NORM_FILTER){
+ char *norm_val = NULL;
+
+ if(ctx->attr_found){
+ slapi_attr_value_normalize(NULL, NULL, ctx->attr , buf, 1,
&norm_val );
+ if(norm_val){
+ buf = norm_val;
+ filter_len = strlen(buf);
+ }
+ }
+ }
+ /*
+ * Escape the filter value
+ */
+ if(ctx->next_arg_needs_esc_norm & ESCAPE_FILTER){
+#if defined (USE_OPENLDAP)
+ raw_filter.bv_val = (char *)buf;
+ raw_filter.bv_len = filter_len;
+ if(ldap_bv2escaped_filter_value(&raw_filter, &escaped_filter) != 0){
+ LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape
filter value(%s)\n",val,0,0);
+ ctx->next_arg_needs_esc_norm = 0;
+ return -1;
+ } else {
+ filter_len = escaped_filter.bv_len;
+ buf = escaped_filter.bv_val;
+ }
+#else
+ buf = slapi_ch_calloc(sizeof(char), filter_len*3 + 1);
+ free_buf = 1;
+ if(do_escape_string(val, filter_len, buf, special_filter) == NULL){
+ LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape
filter value(%s)\n",val,0,0);
+ ctx->next_arg_needs_esc_norm = 0;
+ slapi_ch_free_string(&buf);
+ return -1;
+ } else {
+ filter_len = strlen(buf);
+ }
+#endif
+ }
+
+ /*
+ * Now add the new value to the buffer, and allocate more memory if needed
+ */
+ if (ctx->buf_size + filter_len >= ctx->buf_len){
+ /* increase buffer for this filter */
+ extra_space = (ctx->buf_len + filter_len + BUF_INCR);
+ slapi_ch_realloc(ctx->buf, sizeof(char) * extra_space);
+ ctx->buf_len = extra_space;
+ }
+
+ /* append the escaped value */
+ memcpy(ctx->buf + ctx->buf_size, buf, filter_len);
+ ctx->buf_size += filter_len;
+
+ /* done with the value, reset everything */
+ ctx->next_arg_needs_esc_norm = 0;
+ ctx->attr_found = 0;
+ ctx->attr_position = 0;
+ memset(ctx->attr, '\0', ATTRSIZE);
+ if(free_buf){
+ slapi_ch_free_string(&buf);
+ }
+
+ return filter_len;
+ } else { /* process arg as is */
+ /* check if we have enough room in our buffer */
+ if (ctx->buf_size + slen >= ctx->buf_len){
+ /* increase buffer for this filter */
+ extra_space = (ctx->buf_len + slen + BUF_INCR);
+ ctx->buf = slapi_ch_realloc((char *)ctx->buf, sizeof(char) *
extra_space);
+ ctx->buf_len = extra_space;
+ }
+ memcpy(ctx->buf + ctx->buf_size, buf, slen);
+ ctx->buf_size += slen;
+
+ return slen;
+ }
+}
+
+/*
+ * This is basically like slapi_ch_smprintf() except it can handle special
+ * keywords that will cause the next value to be escaped and/or normalized.
+ *
+ * ESC_NEXT_VAL - escape the next value
+ * NORM_NEXT_VAL - normalize the next value
+ * ESC_AND_NORM_NEXT_VAL - escape and normalize the next value
+ *
+ * Example:
+ *
+ * slapi_filter_sprintf("cn=%s%s", ESC_NEXT_VAL, value);
+ * slapi_filter_sprintf("(|(cn=%s%s)(sn=%s%s))", ESC_NEXT_VAL, value,
NORM_NEXT_VAL, value);
+ *
+ * Note: you need a string format specifier(%s) for each keyword
+ */
+char*
+slapi_filter_sprintf(const char *fmt, ...)
+{
+ struct filter_ctx ctx;
+ va_list args;
+ char *buf;
+ int rc;
+
+ buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1);
+ ctx.buf = buf;
+ memset(ctx.attr,'\0', ATTRSIZE);
+ ctx.attr_position = 0;
+ ctx.attr_found = 0;
+ ctx.buf_len = FILTER_BUF;
+ ctx.buf_size = 0;
+ ctx.next_arg_needs_esc_norm = 0;
+ ctx.skip_escape = 0;
+
+ va_start(args, fmt);
+ rc = PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
+ if(rc == -1){
+ /* transformation failed, just return non-normalized/escaped string */
+ ctx.skip_escape = 1;
+ PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
+ }
+ va_end(args);
+
+ return buf;
+}
+
+/*
+ * escape special characters in values used in search filters
+ *
+ * caller must free the returned value
+ */
+char*
+slapi_escape_filter_value(char* filter_str, int len)
+{
+ struct berval *escaped_filter = NULL;
+ struct berval raw_filter;
+ int filter_len;
+
+ /*
+ * Check the length for special cases
+ */
+ if(len == -1){
+ /* filter str is null terminated */
+ filter_len = strlen(filter_str);
+ } else if (len == 0){
+ /* return the filter as is */
+ return slapi_ch_strdup(filter_str);
+ } else {
+ /* the len is the length */
+ filter_len = len;
+ }
+#if defined (USE_OPENLDAP)
+ /*
+ * Construct the berval and escape it
+ */
+ raw_filter.bv_val = filter_str;
+ raw_filter.bv_len = filter_len;
+ if(ldap_bv2escaped_filter_value(&raw_filter, escaped_filter) != 0){
+ LDAPDebug(LDAP_DEBUG_TRACE, "slapi_escape_filter_value: failed to escape
filter value(%s)\n",filter_str,0,0);
+ return NULL;
+ } else {
+ return slapi_ch_strdup(escaped_filter->bv_val);
+ }
+#else
+ char *buf = slapi_ch_calloc(sizeof(char), filter_len*3+1);
+
+ return do_escape_string(filter_str, filter_len, buf, special_filter);
+#endif
}
/*