Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 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