1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

Always escape ldap filter strings. Escaping code was from pam_ldap, but I'm to

blame for the realloc() stuff.

Plus a couple of minor updates to libads.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett 0001-01-01 00:00:00 +00:00
parent 9494c1e153
commit 34b2e558a4
7 changed files with 164 additions and 16 deletions

90
source/lib/ldap_escape.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {
DEBUG(1, ("ads_set_machine_sd: asprintf failed!\n"));
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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);