Magellan Linux

Annotation of /trunk/samba/patches/samba-3.0.24-shell_escape.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 201 - (hide annotations) (download)
Sat May 19 16:54:40 2007 UTC (17 years ago) by niro
File size: 6234 byte(s)
-added security fixes (CVE-2007-2446 && CVE-2007-2447)

1 niro 201 Only in source-orig/: configure
2     diff -u -r source-orig/lib/charcnv.c source/lib/charcnv.c
3     --- source-orig/lib/charcnv.c 2006-04-19 19:29:23.000000000 -0700
4     +++ source/lib/charcnv.c 2007-05-10 09:59:49.023262000 -0700
5     @@ -1398,5 +1398,5 @@
6     /* We're hosed - we don't know how big this is... */
7     DEBUG(10,("next_mb_char_size: unknown size at string %s\n", s));
8     conv_silent = False;
9     - return 1;
10     + return (size_t)-1;
11     }
12     diff -u -r source-orig/lib/smbrun.c source/lib/smbrun.c
13     --- source-orig/lib/smbrun.c 2006-04-19 19:29:23.000000000 -0700
14     +++ source/lib/smbrun.c 2007-05-10 09:57:03.305061000 -0700
15     @@ -55,7 +55,7 @@
16     outfd (or discard it if outfd is NULL).
17     ****************************************************************************/
18    
19     -int smbrun(const char *cmd, int *outfd)
20     +static int smbrun_internal(const char *cmd, int *outfd, BOOL sanitize)
21     {
22     pid_t pid;
23     uid_t uid = current_user.ut.uid;
24     @@ -173,13 +173,36 @@
25     }
26     #endif
27    
28     - execl("/bin/sh","sh","-c",cmd,NULL);
29     + {
30     + const char *newcmd = sanitize ? escape_shell_string(cmd) : cmd;
31     + if (!newcmd) {
32     + exit(82);
33     + }
34     + execl("/bin/sh","sh","-c",newcmd,NULL);
35     + }
36    
37     /* not reached */
38     - exit(82);
39     + exit(83);
40     return 1;
41     }
42    
43     +/****************************************************************************
44     + Use only in known safe shell calls (printing).
45     +****************************************************************************/
46     +
47     +int smbrun_no_sanitize(const char *cmd, int *outfd)
48     +{
49     + return smbrun_internal(cmd, outfd, False);
50     +}
51     +
52     +/****************************************************************************
53     + By default this now sanitizes shell expansion.
54     +****************************************************************************/
55     +
56     +int smbrun(const char *cmd, int *outfd)
57     +{
58     + return smbrun_internal(cmd, outfd, True);
59     +}
60    
61     /****************************************************************************
62     run a command being careful about uid/gid handling and putting the output in
63     @@ -302,7 +325,7 @@
64     #endif
65    
66     execl("/bin/sh", "sh", "-c", cmd, NULL);
67     -
68     +
69     /* not reached */
70     exit(82);
71     return 1;
72     diff -u -r source-orig/lib/util_str.c source/lib/util_str.c
73     --- source-orig/lib/util_str.c 2007-02-04 10:59:17.000000000 -0800
74     +++ source/lib/util_str.c 2007-05-10 09:59:36.718762000 -0700
75     @@ -2426,3 +2426,165 @@
76     return True;
77     }
78    
79     +
80     +/*******************************************************************
81     + Add a shell escape character '\' to any character not in a known list
82     + of characters. UNIX charset format.
83     +*******************************************************************/
84     +
85     +#define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabdefghijklmnopqrstuvwxyz_/ \t.,"
86     +#define INSIDE_DQUOTE_LIST "$`\n\"\\"
87     +
88     +char *escape_shell_string(const char *src)
89     +{
90     + size_t srclen = strlen(src);
91     + char *ret = SMB_MALLOC((srclen * 2) + 1);
92     + char *dest = ret;
93     + BOOL in_s_quote = False;
94     + BOOL in_d_quote = False;
95     + BOOL next_escaped = False;
96     +
97     + if (!ret) {
98     + return NULL;
99     + }
100     +
101     + while (*src) {
102     + size_t c_size = next_mb_char_size(src);
103     +
104     + if (c_size == (size_t)-1) {
105     + SAFE_FREE(ret);
106     + return NULL;
107     + }
108     +
109     + if (c_size > 1) {
110     + memcpy(dest, src, c_size);
111     + src += c_size;
112     + dest += c_size;
113     + next_escaped = False;
114     + continue;
115     + }
116     +
117     + /*
118     + * Deal with backslash escaped state.
119     + * This only lasts for one character.
120     + */
121     +
122     + if (next_escaped) {
123     + *dest++ = *src++;
124     + next_escaped = False;
125     + continue;
126     + }
127     +
128     + /*
129     + * Deal with single quote state. The
130     + * only thing we care about is exiting
131     + * this state.
132     + */
133     +
134     + if (in_s_quote) {
135     + if (*src == '\'') {
136     + in_s_quote = False;
137     + }
138     + *dest++ = *src++;
139     + continue;
140     + }
141     +
142     + /*
143     + * Deal with double quote state. The most
144     + * complex state. We must cope with \, meaning
145     + * possibly escape next char (depending what it
146     + * is), ", meaning exit this state, and possibly
147     + * add an \ escape to any unprotected character
148     + * (listed in INSIDE_DQUOTE_LIST).
149     + */
150     +
151     + if (in_d_quote) {
152     + if (*src == '\\') {
153     + /*
154     + * Next character might be escaped.
155     + * We have to peek. Inside double
156     + * quotes only INSIDE_DQUOTE_LIST
157     + * characters are escaped by a \.
158     + */
159     +
160     + char nextchar;
161     +
162     + c_size = next_mb_char_size(&src[1]);
163     + if (c_size == (size_t)-1) {
164     + SAFE_FREE(ret);
165     + return NULL;
166     + }
167     + if (c_size > 1) {
168     + /*
169     + * Don't escape the next char.
170     + * Just copy the \.
171     + */
172     + *dest++ = *src++;
173     + continue;
174     + }
175     +
176     + nextchar = src[1];
177     +
178     + if (nextchar && strchr(INSIDE_DQUOTE_LIST, (int)nextchar)) {
179     + next_escaped = True;
180     + }
181     + *dest++ = *src++;
182     + continue;
183     + }
184     +
185     + if (*src == '\"') {
186     + /* Exit double quote state. */
187     + in_d_quote = False;
188     + *dest++ = *src++;
189     + continue;
190     + }
191     +
192     + /*
193     + * We know the character isn't \ or ",
194     + * so escape it if it's any of the other
195     + * possible unprotected characters.
196     + */
197     +
198     + if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
199     + *dest++ = '\\';
200     + }
201     + *dest++ = *src++;
202     + continue;
203     + }
204     +
205     + /*
206     + * From here to the end of the loop we're
207     + * not in the single or double quote state.
208     + */
209     +
210     + if (*src == '\\') {
211     + /* Next character must be escaped. */
212     + next_escaped = True;
213     + *dest++ = *src++;
214     + continue;
215     + }
216     +
217     + if (*src == '\'') {
218     + /* Go into single quote state. */
219     + in_s_quote = True;
220     + *dest++ = *src++;
221     + continue;
222     + }
223     +
224     + if (*src == '\"') {
225     + /* Go into double quote state. */
226     + in_d_quote = True;
227     + *dest++ = *src++;
228     + continue;
229     + }
230     +
231     + /* Check if we need to escape the character. */
232     +
233     + if (!strchr(INCLUDE_LIST, (int)*src)) {
234     + *dest++ = '\\';
235     + }
236     + *dest++ = *src++;
237     + }
238     + *dest++ = '\0';
239     + return ret;
240     +}
241     diff -u -r source-orig/printing/print_generic.c source/printing/print_generic.c
242     --- source-orig/printing/print_generic.c 2007-02-04 10:59:13.000000000 -0800
243     +++ source/printing/print_generic.c 2007-05-10 09:57:03.292061000 -0700
244     @@ -58,7 +58,7 @@
245     if ( do_sub && snum != -1 )
246     standard_sub_snum(snum,syscmd,sizeof(syscmd));
247    
248     - ret = smbrun(syscmd,outfd);
249     + ret = smbrun_no_sanitize(syscmd,outfd);
250    
251     DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
252