mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r22852: merge fixes for CVE-2007-2446 and CVE-2007-2447 to all branches
This commit is contained in:
parent
34f77af02e
commit
f65214be68
@ -295,7 +295,6 @@ copy an IP address from one buffer to another
|
||||
#if defined(PARANOID_MALLOC_CHECKER)
|
||||
|
||||
#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem_((ps),sizeof(type),(count))
|
||||
#define PRS_ALLOC_MEM_VOID(ps, size) prs_alloc_mem_((ps),(size),1)
|
||||
|
||||
/* Get medieval on our ass about malloc.... */
|
||||
|
||||
@ -334,7 +333,6 @@ copy an IP address from one buffer to another
|
||||
#else
|
||||
|
||||
#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem((ps),sizeof(type),(count))
|
||||
#define PRS_ALLOC_MEM_VOID(ps, size) prs_alloc_mem((ps),(size),1)
|
||||
|
||||
/* Regular malloc code. */
|
||||
|
||||
|
@ -55,7 +55,7 @@ run a command being careful about uid/gid handling and putting the output in
|
||||
outfd (or discard it if outfd is NULL).
|
||||
****************************************************************************/
|
||||
|
||||
int smbrun(const char *cmd, int *outfd)
|
||||
static int smbrun_internal(const char *cmd, int *outfd, BOOL sanitize)
|
||||
{
|
||||
pid_t pid;
|
||||
uid_t uid = current_user.ut.uid;
|
||||
@ -173,13 +173,36 @@ int smbrun(const char *cmd, int *outfd)
|
||||
}
|
||||
#endif
|
||||
|
||||
execl("/bin/sh","sh","-c",cmd,NULL);
|
||||
{
|
||||
const char *newcmd = sanitize ? escape_shell_string(cmd) : cmd;
|
||||
if (!newcmd) {
|
||||
exit(82);
|
||||
}
|
||||
execl("/bin/sh","sh","-c",newcmd,NULL);
|
||||
}
|
||||
|
||||
/* not reached */
|
||||
exit(82);
|
||||
exit(83);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Use only in known safe shell calls (printing).
|
||||
****************************************************************************/
|
||||
|
||||
int smbrun_no_sanitize(const char *cmd, int *outfd)
|
||||
{
|
||||
return smbrun_internal(cmd, outfd, False);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
By default this now sanitizes shell expansion.
|
||||
****************************************************************************/
|
||||
|
||||
int smbrun(const char *cmd, int *outfd)
|
||||
{
|
||||
return smbrun_internal(cmd, outfd, True);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
run a command being careful about uid/gid handling and putting the output in
|
||||
|
@ -2616,3 +2616,166 @@ size_t utf16_len_n(const void *src, size_t n)
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Add a shell escape character '\' to any character not in a known list
|
||||
of characters. UNIX charset format.
|
||||
*******************************************************************/
|
||||
|
||||
#define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabdefghijklmnopqrstuvwxyz_/ \t.,"
|
||||
#define INSIDE_DQUOTE_LIST "$`\n\"\\"
|
||||
|
||||
char *escape_shell_string(const char *src)
|
||||
{
|
||||
size_t srclen = strlen(src);
|
||||
char *ret = SMB_MALLOC((srclen * 2) + 1);
|
||||
char *dest = ret;
|
||||
BOOL in_s_quote = False;
|
||||
BOOL in_d_quote = False;
|
||||
BOOL next_escaped = False;
|
||||
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
size_t c_size;
|
||||
codepoint_t c = next_codepoint(src, &c_size);
|
||||
|
||||
if (c == INVALID_CODEPOINT) {
|
||||
SAFE_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c_size > 1) {
|
||||
memcpy(dest, src, c_size);
|
||||
src += c_size;
|
||||
dest += c_size;
|
||||
next_escaped = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with backslash escaped state.
|
||||
* This only lasts for one character.
|
||||
*/
|
||||
|
||||
if (next_escaped) {
|
||||
*dest++ = *src++;
|
||||
next_escaped = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with single quote state. The
|
||||
* only thing we care about is exiting
|
||||
* this state.
|
||||
*/
|
||||
|
||||
if (in_s_quote) {
|
||||
if (*src == '\'') {
|
||||
in_s_quote = False;
|
||||
}
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with double quote state. The most
|
||||
* complex state. We must cope with \, meaning
|
||||
* possibly escape next char (depending what it
|
||||
* is), ", meaning exit this state, and possibly
|
||||
* add an \ escape to any unprotected character
|
||||
* (listed in INSIDE_DQUOTE_LIST).
|
||||
*/
|
||||
|
||||
if (in_d_quote) {
|
||||
if (*src == '\\') {
|
||||
/*
|
||||
* Next character might be escaped.
|
||||
* We have to peek. Inside double
|
||||
* quotes only INSIDE_DQUOTE_LIST
|
||||
* characters are escaped by a \.
|
||||
*/
|
||||
|
||||
char nextchar;
|
||||
|
||||
c = next_codepoint(&src[1], &c_size);
|
||||
if (c == INVALID_CODEPOINT) {
|
||||
SAFE_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
if (c_size > 1) {
|
||||
/*
|
||||
* Don't escape the next char.
|
||||
* Just copy the \.
|
||||
*/
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
nextchar = src[1];
|
||||
|
||||
if (nextchar && strchr(INSIDE_DQUOTE_LIST, (int)nextchar)) {
|
||||
next_escaped = True;
|
||||
}
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*src == '\"') {
|
||||
/* Exit double quote state. */
|
||||
in_d_quote = False;
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We know the character isn't \ or ",
|
||||
* so escape it if it's any of the other
|
||||
* possible unprotected characters.
|
||||
*/
|
||||
|
||||
if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
|
||||
*dest++ = '\\';
|
||||
}
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* From here to the end of the loop we're
|
||||
* not in the single or double quote state.
|
||||
*/
|
||||
|
||||
if (*src == '\\') {
|
||||
/* Next character must be escaped. */
|
||||
next_escaped = True;
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*src == '\'') {
|
||||
/* Go into single quote state. */
|
||||
in_s_quote = True;
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*src == '\"') {
|
||||
/* Go into double quote state. */
|
||||
in_d_quote = True;
|
||||
*dest++ = *src++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if we need to escape the character. */
|
||||
|
||||
if (!strchr(INCLUDE_LIST, (int)*src)) {
|
||||
*dest++ = '\\';
|
||||
}
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest++ = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub,
|
||||
current_user_info.domain,
|
||||
syscmd, sizeof(syscmd));
|
||||
|
||||
ret = smbrun(syscmd,outfd);
|
||||
ret = smbrun_no_sanitize(syscmd,outfd);
|
||||
|
||||
DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
|
||||
|
||||
|
@ -1356,12 +1356,17 @@ static BOOL lsa_io_trans_names(const char *desc, LSA_TRANS_NAME_ENUM *trn,
|
||||
&trn->num_entries2))
|
||||
return False;
|
||||
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if ((trn->name = PRS_ALLOC_MEM(ps, LSA_TRANS_NAME, trn->num_entries)) == NULL) {
|
||||
if (trn->num_entries2 != trn->num_entries) {
|
||||
/* RPC fault */
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((trn->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, trn->num_entries)) == NULL) {
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if ((trn->name = PRS_ALLOC_MEM(ps, LSA_TRANS_NAME, trn->num_entries2)) == NULL) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((trn->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, trn->num_entries2)) == NULL) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -1413,12 +1418,17 @@ static BOOL lsa_io_trans_names2(const char *desc, LSA_TRANS_NAME_ENUM2 *trn,
|
||||
&trn->num_entries2))
|
||||
return False;
|
||||
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if ((trn->name = PRS_ALLOC_MEM(ps, LSA_TRANS_NAME2, trn->num_entries)) == NULL) {
|
||||
if (trn->num_entries2 != trn->num_entries) {
|
||||
/* RPC fault */
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((trn->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, trn->num_entries)) == NULL) {
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if ((trn->name = PRS_ALLOC_MEM(ps, LSA_TRANS_NAME2, trn->num_entries2)) == NULL) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((trn->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, trn->num_entries2)) == NULL) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -2771,7 +2781,7 @@ static BOOL lsa_io_luid_attr(const char *desc, LUID_ATTR *out, prs_struct *ps, i
|
||||
|
||||
static BOOL lsa_io_privilege_set(const char *desc, PRIVILEGE_SET *out, prs_struct *ps, int depth)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 i, dummy;
|
||||
|
||||
prs_debug(ps, depth, desc, "lsa_io_privilege_set");
|
||||
depth++;
|
||||
@ -2779,7 +2789,7 @@ static BOOL lsa_io_privilege_set(const char *desc, PRIVILEGE_SET *out, prs_struc
|
||||
if(!prs_align(ps))
|
||||
return False;
|
||||
|
||||
if(!prs_uint32("count", ps, depth, &out->count))
|
||||
if(!prs_uint32("count", ps, depth, &dummy))
|
||||
return False;
|
||||
if(!prs_uint32("control", ps, depth, &out->control))
|
||||
return False;
|
||||
|
@ -644,7 +644,7 @@ BOOL prs_pointer( const char *name, prs_struct *ps, int depth,
|
||||
return True;
|
||||
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if ( !(*data = PRS_ALLOC_MEM_VOID(ps, data_size)) )
|
||||
if ( !(*data = PRS_ALLOC_MEM(ps, char, data_size)) )
|
||||
return False;
|
||||
}
|
||||
|
||||
|
@ -183,13 +183,12 @@ BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
|
||||
return False;
|
||||
|
||||
if (UNMARSHALLING(ps)) {
|
||||
/*
|
||||
* Even if the num_aces is zero, allocate memory as there's a difference
|
||||
* between a non-present DACL (allow all access) and a DACL with no ACE's
|
||||
* (allow no access).
|
||||
*/
|
||||
if((psa->aces = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces+1)) == NULL)
|
||||
if (psa->num_aces) {
|
||||
if((psa->aces = PRS_ALLOC_MEM(ps, SEC_ACE, psa->num_aces)) == NULL)
|
||||
return False;
|
||||
} else {
|
||||
psa->aces = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < psa->num_aces; i++) {
|
||||
|
@ -230,6 +230,10 @@ static BOOL smb_io_notify_option_type_data(const char *desc, SPOOL_NOTIFY_OPTION
|
||||
if (type->count2 != type->count)
|
||||
DEBUG(4,("What a mess, count was %x now is %x !\n", type->count, type->count2));
|
||||
|
||||
if (type->count2 > MAX_NOTIFY_TYPE_FOR_NOW) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* parse the option type data */
|
||||
for(i=0;i<type->count2;i++)
|
||||
if(!prs_uint16("fields",ps,depth,&type->fields[i]))
|
||||
|
Loading…
Reference in New Issue
Block a user