summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/lib/ldap_escape.c90
-rw-r--r--source3/libads/ads_ldap.c12
-rw-r--r--source3/libads/ldap.c28
-rw-r--r--source3/libads/ldap_user.c9
-rw-r--r--source3/nsswitch/winbindd_ads.c9
-rw-r--r--source3/passdb/pdb_ldap.c22
-rw-r--r--source3/utils/net_ads.c8
7 files changed, 163 insertions, 15 deletions
diff --git a/source3/lib/ldap_escape.c b/source3/lib/ldap_escape.c
new file mode 100644
index 0000000000..9e88b4999c
--- /dev/null
+++ b/source3/lib/ldap_escape.c
@@ -0,0 +1,90 @@
+/*
+ Unix SMB/CIFS implementation.
+ ldap filter argument escaping
+
+ Copyright (C) 1998, 1999, 2000 Luke Howard <lukeh@padl.com>,
+ Copyright (C) 2003 Andrew Bartlett <abartlet@samba.org>
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/**
+ * Escape a parameter to an LDAP filter string, so they cannot contain
+ * embeded ( ) * or \ chars which may cause it not to parse correctly.
+ *
+ * @param s The input string
+ *
+ * @return A string allocated with malloc(), containing the escaped string,
+ * and to be free()ed by the caller.
+ **/
+
+char *escape_ldap_string_alloc(const char *s)
+{
+ size_t len = strlen(s)+1;
+ char *output = malloc(len);
+ char *output_tmp;
+ const char *sub;
+ int i = 0;
+ char *p = output;
+
+ while (*s)
+ {
+ switch (*s)
+ {
+ case '*':
+ sub = "\\2a";
+ break;
+ case '(':
+ sub = "\\28";
+ break;
+ case ')':
+ sub = "\\29";
+ break;
+ case '\\':
+ sub = "\\5c";
+ break;
+ default:
+ sub = NULL;
+ break;
+ }
+
+ if (sub) {
+ len = len + 3;
+ output_tmp = realloc(output, len);
+ if (!output_tmp) {
+ SAFE_FREE(output);
+ return NULL;
+ }
+ output = output_tmp;
+
+ p = &output[i];
+ strncpy (p, sub, 3);
+ p += 3;
+ i += 3;
+
+ } else {
+ *p = *s;
+ p++;
+ i++;
+ }
+ s++;
+ }
+
+ *p = '\0';
+ return output;
+}
diff --git a/source3/libads/ads_ldap.c b/source3/libads/ads_ldap.c
index 05b016539e..97f12de0f7 100644
--- a/source3/libads/ads_ldap.c
+++ b/source3/libads/ads_ldap.c
@@ -37,9 +37,16 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
char *exp;
uint32 t;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ char *escaped_name = escape_ldap_string_alloc(name);
+ char *escaped_realm = escape_ldap_string_alloc(ads->config.realm);
+
+ if (!escaped_name || !escaped_realm) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
if (asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
- name, name, ads->config.realm) == -1) {
+ escaped_name, escaped_name, escaped_realm) == -1) {
DEBUG(1,("ads_name_to_sid: asprintf failed!\n"));
status = NT_STATUS_NO_MEMORY;
goto done;
@@ -77,6 +84,9 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads,
done:
if (res) ads_msgfree(ads, res);
+ SAFE_FREE(escaped_name);
+ SAFE_FREE(escaped_realm);
+
return status;
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 0a95e019bf..603f17c994 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -974,7 +974,7 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods)
/* make sure the end of the list is NULL */
mods[i] = NULL;
- ret = ldap_add_s(ads->ld, utf8_dn ? utf8_dn : new_dn, mods);
+ ret = ldap_add_s(ads->ld, utf8_dn, mods);
SAFE_FREE(utf8_dn);
return ADS_ERROR(ret);
}
@@ -994,7 +994,7 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn)
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- ret = ldap_delete(ads->ld, utf8_dn ? utf8_dn : del_dn);
+ ret = ldap_delete(ads->ld, utf8_dn);
return ADS_ERROR(ret);
}
@@ -1029,8 +1029,8 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
ADS_MODLIST mods;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
- const char *servicePrincipalName[3] = {NULL, NULL, NULL};
- char *psp;
+ const char *servicePrincipalName[5] = {NULL, NULL, NULL, NULL, NULL};
+ char *psp, *psp2;
unsigned acct_control;
if (!(ctx = talloc_init("machine_account")))
@@ -1051,10 +1051,16 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
ads->config.bind_path);
servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", hostname);
psp = talloc_asprintf(ctx, "HOST/%s.%s",
- hostname,
- ads->config.realm);
+ hostname,
+ ads->config.realm);
strlower(&psp[5]);
servicePrincipalName[1] = psp;
+ servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", hostname);
+ psp2 = talloc_asprintf(ctx, "CIFS/%s.%s",
+ hostname,
+ ads->config.realm);
+ strlower(&psp2[5]);
+ servicePrincipalName[3] = psp2;
free(ou_str);
if (!new_dn)
@@ -1405,6 +1411,7 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
size_t sd_size = 0;
struct berval bval = {0, NULL};
prs_struct ps_wire;
+ char *escaped_hostname = escape_ldap_string_alloc(hostname);
LDAPMessage *res = 0;
LDAPMessage *msg = 0;
@@ -1420,11 +1427,18 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
ret = ADS_ERROR(LDAP_SUCCESS);
- if (asprintf(&exp, "(samAccountName=%s$)", hostname) == -1) {
+ if (!escaped_hostname) {
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ if (asprintf(&exp, "(samAccountName=%s$)", escaped_hostname) == -1) {
DEBUG(1, ("ads_set_machine_sd: asprintf failed!\n"));
+ SAFE_FREE(escaped_hostname);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
+ SAFE_FREE(escaped_hostname);
+
ret = ads_search(ads, (void *) &res, exp, attrs);
if (!ADS_ERR_OK(ret)) return ret;
diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c
index 2e38e7a00d..7efe5338f3 100644
--- a/source3/libads/ldap_user.c
+++ b/source3/libads/ldap_user.c
@@ -30,10 +30,15 @@ ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user)
ADS_STATUS status;
char *exp;
const char *attrs[] = {"*", NULL};
+ char *escaped_user = escape_ldap_string_alloc(user);
+ if (!escaped_user) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
- asprintf(&exp, "(samAccountName=%s)", user);
+ asprintf(&exp, "(samAccountName=%s)", escaped_user);
status = ads_search(ads, res, exp, attrs);
- free(exp);
+ SAFE_FREE(exp);
+ SAFE_FREE(escaped_user);
return status;
}
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 261c2f2237..7cea4aa716 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -346,10 +346,17 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
ADS_STATUS rc;
uint32 atype;
DOM_SID sid;
+ char *escaped_dn = escape_ldap_string_alloc(dn);
+
+ if (!escaped_dn) {
+ return False;
+ }
asprintf(&exp, "(distinguishedName=%s)", dn);
rc = ads_search_retry(ads, &res, exp, attrs);
- free(exp);
+ SAFE_FREE(exp);
+ SAFE_FREE(escaped_dn);
+
if (!ADS_ERR_OK(rc)) {
goto failed;
}
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index e98a2cf04f..6f46201d8d 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -666,7 +666,12 @@ static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state,
LDAPMessage ** result)
{
pstring filter;
-
+ char *escape_user = escape_ldap_string_alloc(user);
+
+ if (!escape_user) {
+ return LDAP_NO_MEMORY;
+ }
+
/*
* in the filter expression, replace %u with the real name
* so in ldap filter, %u MUST exist :-)
@@ -677,7 +682,10 @@ static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state,
* have to use this here because $ is filtered out
* in pstring_sub
*/
- all_string_sub(filter, "%u", user, sizeof(pstring));
+
+
+ all_string_sub(filter, "%u", escape_user, sizeof(pstring));
+ SAFE_FREE(escape_user);
return ldapsam_search_one_user(ldap_state, filter, result);
}
@@ -691,6 +699,7 @@ static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
{
struct passwd *user;
pstring filter;
+ char *escape_user;
/* Get the username from the system and look that up in the LDAP */
@@ -701,9 +710,16 @@ static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
pstrcpy(filter, lp_ldap_filter());
- all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
+ escape_user = escape_ldap_string_alloc(user->pw_name);
+ if (!escape_user) {
+ passwd_free(&user);
+ return LDAP_NO_MEMORY;
+ }
+
+ all_string_sub(filter, "%u", escape_user, sizeof(pstring));
passwd_free(&user);
+ SAFE_FREE(escape_user);
return ldapsam_search_one_user(ldap_state, filter, result);
}
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 29abc33fdf..867252c95f 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -308,12 +308,18 @@ static int ads_user_info(int argc, const char **argv)
const char *attrs[] = {"memberOf", NULL};
char *searchstring=NULL;
char **grouplist;
+ char *escaped_user = escape_ldap_string_alloc(argv[0]);
if (argc < 1) return net_ads_user_usage(argc, argv);
if (!(ads = ads_startup())) return -1;
- asprintf(&searchstring, "(sAMAccountName=%s)", argv[0]);
+ if (!escaped_user) {
+ d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
+ return -1;
+ }
+
+ asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
rc = ads_search(ads, &res, searchstring, attrs);
safe_free(searchstring);