diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-26 10:07:41 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-26 10:07:41 +0000 |
commit | 8b8c75e6abc9283cbdbe6a76e0c4db6098f73ed8 (patch) | |
tree | a4b6c1e8a786fc9f0a42a5a3884dfdc914c30a9d | |
parent | a552eeb498e0270ae9c87ef707865a764df99fb6 (diff) | |
download | busybox-w32-8b8c75e6abc9283cbdbe6a76e0c4db6098f73ed8.tar.gz busybox-w32-8b8c75e6abc9283cbdbe6a76e0c4db6098f73ed8.tar.bz2 busybox-w32-8b8c75e6abc9283cbdbe6a76e0c4db6098f73ed8.zip |
httpd: sanitize indentation
-rw-r--r-- | networking/httpd.c | 2422 |
1 files changed, 1209 insertions, 1213 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 9a8fc685a..9c3c85861 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -133,54 +133,53 @@ typedef struct HT_ACCESS_IP { | |||
133 | struct HT_ACCESS_IP *next; | 133 | struct HT_ACCESS_IP *next; |
134 | } Htaccess_IP; | 134 | } Htaccess_IP; |
135 | 135 | ||
136 | typedef struct | 136 | typedef struct { |
137 | { | 137 | char buf[MAX_MEMORY_BUFF]; |
138 | char buf[MAX_MEMORY_BUFF]; | ||
139 | 138 | ||
140 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;) | 139 | USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;) |
141 | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) | 140 | USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) |
142 | 141 | ||
143 | const char *query; | 142 | const char *query; |
144 | 143 | ||
145 | USE_FEATURE_HTTPD_CGI(char *referer;) | 144 | USE_FEATURE_HTTPD_CGI(char *referer;) |
146 | 145 | ||
147 | const char *configFile; | 146 | const char *configFile; |
148 | 147 | ||
149 | unsigned int rmt_ip; | 148 | unsigned int rmt_ip; |
150 | #if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG | 149 | #if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG |
151 | char rmt_ip_str[16]; /* for set env REMOTE_ADDR */ | 150 | char rmt_ip_str[16]; /* for set env REMOTE_ADDR */ |
152 | #endif | 151 | #endif |
153 | unsigned port; /* server initial port and for | 152 | unsigned port; /* server initial port and for |
154 | set env REMOTE_PORT */ | 153 | set env REMOTE_PORT */ |
155 | union HTTPD_FOUND { | 154 | union HTTPD_FOUND { |
156 | const char *found_mime_type; | 155 | const char *found_mime_type; |
157 | const char *found_moved_temporarily; | 156 | const char *found_moved_temporarily; |
158 | } httpd_found; | 157 | } httpd_found; |
159 | 158 | ||
160 | off_t ContentLength; /* -1 - unknown */ | 159 | off_t ContentLength; /* -1 - unknown */ |
161 | time_t last_mod; | 160 | time_t last_mod; |
162 | 161 | ||
163 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ | 162 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ |
164 | int flg_deny_all; | 163 | int flg_deny_all; |
165 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 164 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
166 | Htaccess *auth; /* config user:password lines */ | 165 | Htaccess *auth; /* config user:password lines */ |
167 | #endif | 166 | #endif |
168 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 167 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
169 | Htaccess *mime_a; /* config mime types */ | 168 | Htaccess *mime_a; /* config mime types */ |
170 | #endif | 169 | #endif |
171 | 170 | ||
172 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 171 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
173 | int accepted_socket; | 172 | int accepted_socket; |
174 | # define a_c_r config->accepted_socket | 173 | # define a_c_r config->accepted_socket |
175 | # define a_c_w config->accepted_socket | 174 | # define a_c_w config->accepted_socket |
176 | #else | 175 | #else |
177 | # define a_c_r 0 | 176 | # define a_c_r 0 |
178 | # define a_c_w 1 | 177 | # define a_c_w 1 |
179 | #endif | 178 | #endif |
180 | volatile int alarm_signaled; | 179 | volatile int alarm_signaled; |
181 | 180 | ||
182 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 181 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
183 | Htaccess *script_i; /* config script interpreters */ | 182 | Htaccess *script_i; /* config script interpreters */ |
184 | #endif | 183 | #endif |
185 | } HttpdConfig; | 184 | } HttpdConfig; |
186 | 185 | ||
@@ -190,86 +189,86 @@ static const char request_GET[] = "GET"; /* size algorithmic optimize */ | |||
190 | 189 | ||
191 | static const char* const suffixTable [] = { | 190 | static const char* const suffixTable [] = { |
192 | /* Warning: shorted equivalent suffix in one line must be first */ | 191 | /* Warning: shorted equivalent suffix in one line must be first */ |
193 | ".htm.html", "text/html", | 192 | ".htm.html", "text/html", |
194 | ".jpg.jpeg", "image/jpeg", | 193 | ".jpg.jpeg", "image/jpeg", |
195 | ".gif", "image/gif", | 194 | ".gif", "image/gif", |
196 | ".png", "image/png", | 195 | ".png", "image/png", |
197 | ".txt.h.c.cc.cpp", "text/plain", | 196 | ".txt.h.c.cc.cpp", "text/plain", |
198 | ".css", "text/css", | 197 | ".css", "text/css", |
199 | ".wav", "audio/wav", | 198 | ".wav", "audio/wav", |
200 | ".avi", "video/x-msvideo", | 199 | ".avi", "video/x-msvideo", |
201 | ".qt.mov", "video/quicktime", | 200 | ".qt.mov", "video/quicktime", |
202 | ".mpe.mpeg", "video/mpeg", | 201 | ".mpe.mpeg", "video/mpeg", |
203 | ".mid.midi", "audio/midi", | 202 | ".mid.midi", "audio/midi", |
204 | ".mp3", "audio/mpeg", | 203 | ".mp3", "audio/mpeg", |
205 | #if 0 /* unpopular */ | 204 | #if 0 /* unpopular */ |
206 | ".au", "audio/basic", | 205 | ".au", "audio/basic", |
207 | ".pac", "application/x-ns-proxy-autoconfig", | 206 | ".pac", "application/x-ns-proxy-autoconfig", |
208 | ".vrml.wrl", "model/vrml", | 207 | ".vrml.wrl", "model/vrml", |
209 | #endif | 208 | #endif |
210 | 0, "application/octet-stream" /* default */ | 209 | 0, "application/octet-stream" /* default */ |
211 | }; | 210 | }; |
212 | 211 | ||
213 | typedef enum | 212 | typedef enum |
214 | { | 213 | { |
215 | HTTP_OK = 200, | 214 | HTTP_OK = 200, |
216 | HTTP_MOVED_TEMPORARILY = 302, | 215 | HTTP_MOVED_TEMPORARILY = 302, |
217 | HTTP_BAD_REQUEST = 400, /* malformed syntax */ | 216 | HTTP_BAD_REQUEST = 400, /* malformed syntax */ |
218 | HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */ | 217 | HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */ |
219 | HTTP_NOT_FOUND = 404, | 218 | HTTP_NOT_FOUND = 404, |
220 | HTTP_FORBIDDEN = 403, | 219 | HTTP_FORBIDDEN = 403, |
221 | HTTP_REQUEST_TIMEOUT = 408, | 220 | HTTP_REQUEST_TIMEOUT = 408, |
222 | HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */ | 221 | HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */ |
223 | HTTP_INTERNAL_SERVER_ERROR = 500, | 222 | HTTP_INTERNAL_SERVER_ERROR = 500, |
224 | #if 0 /* future use */ | 223 | #if 0 /* future use */ |
225 | HTTP_CONTINUE = 100, | 224 | HTTP_CONTINUE = 100, |
226 | HTTP_SWITCHING_PROTOCOLS = 101, | 225 | HTTP_SWITCHING_PROTOCOLS = 101, |
227 | HTTP_CREATED = 201, | 226 | HTTP_CREATED = 201, |
228 | HTTP_ACCEPTED = 202, | 227 | HTTP_ACCEPTED = 202, |
229 | HTTP_NON_AUTHORITATIVE_INFO = 203, | 228 | HTTP_NON_AUTHORITATIVE_INFO = 203, |
230 | HTTP_NO_CONTENT = 204, | 229 | HTTP_NO_CONTENT = 204, |
231 | HTTP_MULTIPLE_CHOICES = 300, | 230 | HTTP_MULTIPLE_CHOICES = 300, |
232 | HTTP_MOVED_PERMANENTLY = 301, | 231 | HTTP_MOVED_PERMANENTLY = 301, |
233 | HTTP_NOT_MODIFIED = 304, | 232 | HTTP_NOT_MODIFIED = 304, |
234 | HTTP_PAYMENT_REQUIRED = 402, | 233 | HTTP_PAYMENT_REQUIRED = 402, |
235 | HTTP_BAD_GATEWAY = 502, | 234 | HTTP_BAD_GATEWAY = 502, |
236 | HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */ | 235 | HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */ |
237 | HTTP_RESPONSE_SETSIZE=0xffffffff | 236 | HTTP_RESPONSE_SETSIZE = 0xffffffff |
238 | #endif | 237 | #endif |
239 | } HttpResponseNum; | 238 | } HttpResponseNum; |
240 | 239 | ||
241 | typedef struct | 240 | typedef struct |
242 | { | 241 | { |
243 | HttpResponseNum type; | 242 | HttpResponseNum type; |
244 | const char *name; | 243 | const char *name; |
245 | const char *info; | 244 | const char *info; |
246 | } HttpEnumString; | 245 | } HttpEnumString; |
247 | 246 | ||
248 | static const HttpEnumString httpResponseNames[] = { | 247 | static const HttpEnumString httpResponseNames[] = { |
249 | { HTTP_OK, "OK", NULL }, | 248 | { HTTP_OK, "OK", NULL }, |
250 | { HTTP_MOVED_TEMPORARILY, "Found", "Directories must end with a slash." }, | 249 | { HTTP_MOVED_TEMPORARILY, "Found", "Directories must end with a slash." }, |
251 | { HTTP_REQUEST_TIMEOUT, "Request Timeout", | 250 | { HTTP_REQUEST_TIMEOUT, "Request Timeout", |
252 | "No request appeared within a reasonable time period." }, | 251 | "No request appeared within a reasonable time period." }, |
253 | { HTTP_NOT_IMPLEMENTED, "Not Implemented", | 252 | { HTTP_NOT_IMPLEMENTED, "Not Implemented", |
254 | "The requested method is not recognized by this server." }, | 253 | "The requested method is not recognized by this server." }, |
255 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 254 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
256 | { HTTP_UNAUTHORIZED, "Unauthorized", "" }, | 255 | { HTTP_UNAUTHORIZED, "Unauthorized", "" }, |
257 | #endif | 256 | #endif |
258 | { HTTP_NOT_FOUND, "Not Found", | 257 | { HTTP_NOT_FOUND, "Not Found", |
259 | "The requested URL was not found on this server." }, | 258 | "The requested URL was not found on this server." }, |
260 | { HTTP_BAD_REQUEST, "Bad Request", "Unsupported method." }, | 259 | { HTTP_BAD_REQUEST, "Bad Request", "Unsupported method." }, |
261 | { HTTP_FORBIDDEN, "Forbidden", "" }, | 260 | { HTTP_FORBIDDEN, "Forbidden", "" }, |
262 | { HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error", | 261 | { HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error", |
263 | "Internal Server Error" }, | 262 | "Internal Server Error" }, |
264 | #if 0 /* not implemented */ | 263 | #if 0 /* not implemented */ |
265 | { HTTP_CREATED, "Created" }, | 264 | { HTTP_CREATED, "Created" }, |
266 | { HTTP_ACCEPTED, "Accepted" }, | 265 | { HTTP_ACCEPTED, "Accepted" }, |
267 | { HTTP_NO_CONTENT, "No Content" }, | 266 | { HTTP_NO_CONTENT, "No Content" }, |
268 | { HTTP_MULTIPLE_CHOICES, "Multiple Choices" }, | 267 | { HTTP_MULTIPLE_CHOICES, "Multiple Choices" }, |
269 | { HTTP_MOVED_PERMANENTLY, "Moved Permanently" }, | 268 | { HTTP_MOVED_PERMANENTLY, "Moved Permanently" }, |
270 | { HTTP_NOT_MODIFIED, "Not Modified" }, | 269 | { HTTP_NOT_MODIFIED, "Not Modified" }, |
271 | { HTTP_BAD_GATEWAY, "Bad Gateway", "" }, | 270 | { HTTP_BAD_GATEWAY, "Bad Gateway", "" }, |
272 | { HTTP_SERVICE_UNAVAILABLE, "Service Unavailable", "" }, | 271 | { HTTP_SERVICE_UNAVAILABLE, "Service Unavailable", "" }, |
273 | #endif | 272 | #endif |
274 | }; | 273 | }; |
275 | 274 | ||
@@ -281,91 +280,91 @@ static const char Content_length[] = "Content-length:"; | |||
281 | static int | 280 | static int |
282 | scan_ip (const char **ep, unsigned int *ip, unsigned char endc) | 281 | scan_ip (const char **ep, unsigned int *ip, unsigned char endc) |
283 | { | 282 | { |
284 | const char *p = *ep; | 283 | const char *p = *ep; |
285 | int auto_mask = 8; | 284 | int auto_mask = 8; |
286 | int j; | 285 | int j; |
287 | 286 | ||
288 | *ip = 0; | 287 | *ip = 0; |
289 | for (j = 0; j < 4; j++) { | 288 | for (j = 0; j < 4; j++) { |
290 | unsigned int octet; | 289 | unsigned int octet; |
291 | 290 | ||
292 | if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) | 291 | if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0) |
293 | return -auto_mask; | 292 | return -auto_mask; |
294 | octet = 0; | 293 | octet = 0; |
295 | while (*p >= '0' && *p <= '9') { | 294 | while (*p >= '0' && *p <= '9') { |
296 | octet *= 10; | 295 | octet *= 10; |
297 | octet += *p - '0'; | 296 | octet += *p - '0'; |
298 | if (octet > 255) | 297 | if (octet > 255) |
299 | return -auto_mask; | 298 | return -auto_mask; |
300 | p++; | 299 | p++; |
300 | } | ||
301 | if (*p == '.') | ||
302 | p++; | ||
303 | if (*p != '/' && *p != 0) | ||
304 | auto_mask += 8; | ||
305 | *ip = ((*ip) << 8) | octet; | ||
301 | } | 306 | } |
302 | if (*p == '.') | 307 | if (*p != 0) { |
303 | p++; | 308 | if (*p != endc) |
304 | if (*p != '/' && *p != 0) | 309 | return -auto_mask; |
305 | auto_mask += 8; | 310 | p++; |
306 | *ip = ((*ip) << 8) | octet; | 311 | if (*p == 0) |
307 | } | 312 | return -auto_mask; |
308 | if (*p != 0) { | 313 | } |
309 | if (*p != endc) | 314 | *ep = p; |
310 | return -auto_mask; | 315 | return auto_mask; |
311 | p++; | ||
312 | if(*p == 0) | ||
313 | return -auto_mask; | ||
314 | } | ||
315 | *ep = p; | ||
316 | return auto_mask; | ||
317 | } | 316 | } |
318 | 317 | ||
319 | static int | 318 | static int |
320 | scan_ip_mask (const char *ipm, unsigned int *ip, unsigned int *mask) | 319 | scan_ip_mask (const char *ipm, unsigned int *ip, unsigned int *mask) |
321 | { | 320 | { |
322 | int i; | 321 | int i; |
323 | unsigned int msk; | 322 | unsigned int msk; |
324 | 323 | ||
325 | i = scan_ip(&ipm, ip, '/'); | 324 | i = scan_ip(&ipm, ip, '/'); |
326 | if(i < 0) | 325 | if (i < 0) |
327 | return i; | 326 | return i; |
328 | if(*ipm) { | 327 | if (*ipm) { |
329 | const char *p = ipm; | 328 | const char *p = ipm; |
330 | 329 | ||
331 | i = 0; | 330 | i = 0; |
332 | while (*p) { | 331 | while (*p) { |
333 | if (*p < '0' || *p > '9') { | 332 | if (*p < '0' || *p > '9') { |
334 | if (*p == '.') { | 333 | if (*p == '.') { |
335 | i = scan_ip (&ipm, mask, 0); | 334 | i = scan_ip (&ipm, mask, 0); |
336 | return i != 32; | 335 | return i != 32; |
337 | } | 336 | } |
338 | return -1; | 337 | return -1; |
338 | } | ||
339 | i *= 10; | ||
340 | i += *p - '0'; | ||
341 | p++; | ||
339 | } | 342 | } |
340 | i *= 10; | ||
341 | i += *p - '0'; | ||
342 | p++; | ||
343 | } | 343 | } |
344 | } | 344 | if (i > 32 || i < 0) |
345 | if (i > 32 || i < 0) | 345 | return -1; |
346 | return -1; | 346 | msk = 0x80000000; |
347 | msk = 0x80000000; | 347 | *mask = 0; |
348 | *mask = 0; | 348 | while (i > 0) { |
349 | while (i > 0) { | 349 | *mask |= msk; |
350 | *mask |= msk; | 350 | msk >>= 1; |
351 | msk >>= 1; | 351 | i--; |
352 | i--; | 352 | } |
353 | } | 353 | return 0; |
354 | return 0; | ||
355 | } | 354 | } |
356 | 355 | ||
357 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) | 356 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) |
358 | static void free_config_lines(Htaccess **pprev) | 357 | static void free_config_lines(Htaccess **pprev) |
359 | { | 358 | { |
360 | Htaccess *prev = *pprev; | 359 | Htaccess *prev = *pprev; |
361 | 360 | ||
362 | while( prev ) { | 361 | while (prev) { |
363 | Htaccess *cur = prev; | 362 | Htaccess *cur = prev; |
364 | 363 | ||
365 | prev = cur->next; | 364 | prev = cur->next; |
366 | free(cur); | 365 | free(cur); |
367 | } | 366 | } |
368 | *pprev = NULL; | 367 | *pprev = NULL; |
369 | } | 368 | } |
370 | #endif | 369 | #endif |
371 | 370 | ||
@@ -401,240 +400,240 @@ static void free_config_lines(Htaccess **pprev) | |||
401 | ****************************************************************************/ | 400 | ****************************************************************************/ |
402 | static void parse_conf(const char *path, int flag) | 401 | static void parse_conf(const char *path, int flag) |
403 | { | 402 | { |
404 | FILE *f; | 403 | FILE *f; |
405 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 404 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
406 | Htaccess *prev, *cur; | 405 | Htaccess *prev, *cur; |
407 | #elif CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 406 | #elif CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
408 | Htaccess *cur; | 407 | Htaccess *cur; |
409 | #endif | 408 | #endif |
410 | 409 | ||
411 | const char *cf = config->configFile; | 410 | const char *cf = config->configFile; |
412 | char buf[160]; | 411 | char buf[160]; |
413 | char *p0 = NULL; | 412 | char *p0 = NULL; |
414 | char *c, *p; | 413 | char *c, *p; |
415 | 414 | ||
416 | /* free previous ip setup if present */ | 415 | /* free previous ip setup if present */ |
417 | Htaccess_IP *pip = config->ip_a_d; | 416 | Htaccess_IP *pip = config->ip_a_d; |
418 | 417 | ||
419 | while( pip ) { | 418 | while (pip) { |
420 | Htaccess_IP *cur_ipl = pip; | 419 | Htaccess_IP *cur_ipl = pip; |
421 | 420 | ||
422 | pip = cur_ipl->next; | 421 | pip = cur_ipl->next; |
423 | free(cur_ipl); | 422 | free(cur_ipl); |
424 | } | 423 | } |
425 | config->ip_a_d = NULL; | 424 | config->ip_a_d = NULL; |
426 | 425 | ||
427 | config->flg_deny_all = 0; | 426 | config->flg_deny_all = 0; |
428 | 427 | ||
429 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR) | 428 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR) |
430 | /* retain previous auth and mime config only for subdir parse */ | 429 | /* retain previous auth and mime config only for subdir parse */ |
431 | if(flag != SUBDIR_PARSE) { | 430 | if (flag != SUBDIR_PARSE) { |
432 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 431 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
433 | free_config_lines(&config->auth); | 432 | free_config_lines(&config->auth); |
434 | #endif | 433 | #endif |
435 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 434 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
436 | free_config_lines(&config->mime_a); | 435 | free_config_lines(&config->mime_a); |
437 | #endif | 436 | #endif |
438 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 437 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
439 | free_config_lines(&config->script_i); | 438 | free_config_lines(&config->script_i); |
440 | #endif | 439 | #endif |
441 | } | 440 | } |
442 | #endif | 441 | #endif |
443 | 442 | ||
444 | if(flag == SUBDIR_PARSE || cf == NULL) { | 443 | if (flag == SUBDIR_PARSE || cf == NULL) { |
445 | cf = alloca(strlen(path) + sizeof(httpd_conf) + 2); | 444 | cf = alloca(strlen(path) + sizeof(httpd_conf) + 2); |
446 | if(cf == NULL) { | 445 | if (cf == NULL) { |
447 | if(flag == FIRST_PARSE) | 446 | if (flag == FIRST_PARSE) |
448 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 447 | bb_error_msg_and_die(bb_msg_memory_exhausted); |
449 | return; | 448 | return; |
449 | } | ||
450 | sprintf((char *)cf, "%s/%s", path, httpd_conf); | ||
450 | } | 451 | } |
451 | sprintf((char *)cf, "%s/%s", path, httpd_conf); | ||
452 | } | ||
453 | 452 | ||
454 | while((f = fopen(cf, "r")) == NULL) { | 453 | while ((f = fopen(cf, "r")) == NULL) { |
455 | if(flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) { | 454 | if (flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) { |
456 | /* config file not found, no changes to config */ | 455 | /* config file not found, no changes to config */ |
457 | return; | 456 | return; |
457 | } | ||
458 | if (config->configFile && flag == FIRST_PARSE) /* if -c option given */ | ||
459 | bb_perror_msg_and_die("%s", cf); | ||
460 | flag = FIND_FROM_HTTPD_ROOT; | ||
461 | cf = httpd_conf; | ||
458 | } | 462 | } |
459 | if(config->configFile && flag == FIRST_PARSE) /* if -c option given */ | ||
460 | bb_perror_msg_and_die("%s", cf); | ||
461 | flag = FIND_FROM_HTTPD_ROOT; | ||
462 | cf = httpd_conf; | ||
463 | } | ||
464 | 463 | ||
465 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 464 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
466 | prev = config->auth; | 465 | prev = config->auth; |
467 | #endif | 466 | #endif |
468 | /* This could stand some work */ | 467 | /* This could stand some work */ |
469 | while ( (p0 = fgets(buf, sizeof(buf), f)) != NULL) { | 468 | while ( (p0 = fgets(buf, sizeof(buf), f)) != NULL) { |
470 | c = NULL; | 469 | c = NULL; |
471 | for(p = p0; *p0 != 0 && *p0 != '#'; p0++) { | 470 | for (p = p0; *p0 != 0 && *p0 != '#'; p0++) { |
472 | if(!isspace(*p0)) { | 471 | if (!isspace(*p0)) { |
473 | *p++ = *p0; | 472 | *p++ = *p0; |
474 | if(*p0 == ':' && c == NULL) | 473 | if (*p0 == ':' && c == NULL) |
475 | c = p; | 474 | c = p; |
475 | } | ||
476 | } | ||
477 | *p = 0; | ||
478 | |||
479 | /* test for empty or strange line */ | ||
480 | if (c == NULL || *c == 0) | ||
481 | continue; | ||
482 | p0 = buf; | ||
483 | if (*p0 == 'd') | ||
484 | *p0 = 'D'; | ||
485 | if (*c == '*') { | ||
486 | if (*p0 == 'D') { | ||
487 | /* memorize deny all */ | ||
488 | config->flg_deny_all++; | ||
489 | } | ||
490 | /* skip default other "word:*" config lines */ | ||
491 | continue; | ||
476 | } | 492 | } |
477 | } | ||
478 | *p = 0; | ||
479 | |||
480 | /* test for empty or strange line */ | ||
481 | if (c == NULL || *c == 0) | ||
482 | continue; | ||
483 | p0 = buf; | ||
484 | if(*p0 == 'd') | ||
485 | *p0 = 'D'; | ||
486 | if(*c == '*') { | ||
487 | if(*p0 == 'D') { | ||
488 | /* memorize deny all */ | ||
489 | config->flg_deny_all++; | ||
490 | } | ||
491 | /* skip default other "word:*" config lines */ | ||
492 | continue; | ||
493 | } | ||
494 | 493 | ||
495 | if(*p0 == 'a') | 494 | if (*p0 == 'a') |
496 | *p0 = 'A'; | 495 | *p0 = 'A'; |
497 | else if(*p0 != 'D' && *p0 != 'A' | 496 | else if (*p0 != 'D' && *p0 != 'A' |
498 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 497 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
499 | && *p0 != '/' | 498 | && *p0 != '/' |
500 | #endif | 499 | #endif |
501 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 500 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
502 | && *p0 != '.' | 501 | && *p0 != '.' |
503 | #endif | 502 | #endif |
504 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 503 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
505 | && *p0 != '*' | 504 | && *p0 != '*' |
506 | #endif | 505 | #endif |
507 | ) | 506 | ) |
508 | continue; | 507 | continue; |
509 | if(*p0 == 'A' || *p0 == 'D') { | 508 | if (*p0 == 'A' || *p0 == 'D') { |
510 | /* storing current config IP line */ | 509 | /* storing current config IP line */ |
511 | pip = calloc(1, sizeof(Htaccess_IP)); | 510 | pip = calloc(1, sizeof(Htaccess_IP)); |
512 | if(pip) { | 511 | if (pip) { |
513 | if(scan_ip_mask (c, &(pip->ip), &(pip->mask))) { | 512 | if (scan_ip_mask (c, &(pip->ip), &(pip->mask))) { |
514 | /* syntax IP{/mask} error detected, protect all */ | 513 | /* syntax IP{/mask} error detected, protect all */ |
515 | *p0 = 'D'; | 514 | *p0 = 'D'; |
516 | pip->mask = 0; | 515 | pip->mask = 0; |
517 | } | 516 | } |
518 | pip->allow_deny = *p0; | 517 | pip->allow_deny = *p0; |
519 | if(*p0 == 'D') { | 518 | if (*p0 == 'D') { |
520 | /* Deny:form_IP move top */ | 519 | /* Deny:form_IP move top */ |
521 | pip->next = config->ip_a_d; | 520 | pip->next = config->ip_a_d; |
522 | config->ip_a_d = pip; | 521 | config->ip_a_d = pip; |
523 | } else { | 522 | } else { |
524 | /* add to bottom A:form_IP config line */ | 523 | /* add to bottom A:form_IP config line */ |
525 | Htaccess_IP *prev_IP = config->ip_a_d; | 524 | Htaccess_IP *prev_IP = config->ip_a_d; |
526 | 525 | ||
527 | if(prev_IP == NULL) { | 526 | if (prev_IP == NULL) { |
528 | config->ip_a_d = pip; | 527 | config->ip_a_d = pip; |
529 | } else { | 528 | } else { |
530 | while(prev_IP->next) | 529 | while (prev_IP->next) |
531 | prev_IP = prev_IP->next; | 530 | prev_IP = prev_IP->next; |
532 | prev_IP->next = pip; | 531 | prev_IP->next = pip; |
532 | } | ||
533 | } | ||
533 | } | 534 | } |
534 | } | 535 | continue; |
535 | } | 536 | } |
536 | continue; | ||
537 | } | ||
538 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 537 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
539 | if(*p0 == '/') { | 538 | if (*p0 == '/') { |
540 | /* make full path from httpd root / curent_path / config_line_path */ | 539 | /* make full path from httpd root / curent_path / config_line_path */ |
541 | cf = flag == SUBDIR_PARSE ? path : ""; | 540 | cf = flag == SUBDIR_PARSE ? path : ""; |
542 | p0 = malloc(strlen(cf) + (c - buf) + 2 + strlen(c)); | 541 | p0 = malloc(strlen(cf) + (c - buf) + 2 + strlen(c)); |
543 | if(p0 == NULL) | 542 | if (p0 == NULL) |
544 | continue; | ||
545 | c[-1] = 0; | ||
546 | sprintf(p0, "/%s%s", cf, buf); | ||
547 | |||
548 | /* another call bb_simplify_path */ | ||
549 | cf = p = p0; | ||
550 | |||
551 | do { | ||
552 | if (*p == '/') { | ||
553 | if (*cf == '/') { /* skip duplicate (or initial) slash */ | ||
554 | continue; | ||
555 | } else if (*cf == '.') { | ||
556 | if (cf[1] == '/' || cf[1] == 0) { /* remove extra '.' */ | ||
557 | continue; | 543 | continue; |
558 | } else if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == 0)) { | 544 | c[-1] = 0; |
559 | ++cf; | 545 | sprintf(p0, "/%s%s", cf, buf); |
560 | if (p > p0) { | 546 | |
561 | while (*--p != '/'); /* omit previous dir */ | 547 | /* another call bb_simplify_path */ |
548 | cf = p = p0; | ||
549 | |||
550 | do { | ||
551 | if (*p == '/') { | ||
552 | if (*cf == '/') { /* skip duplicate (or initial) slash */ | ||
553 | continue; | ||
554 | } else if (*cf == '.') { | ||
555 | if (cf[1] == '/' || cf[1] == 0) { /* remove extra '.' */ | ||
556 | continue; | ||
557 | } else if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == 0)) { | ||
558 | ++cf; | ||
559 | if (p > p0) { | ||
560 | while (*--p != '/'); /* omit previous dir */ | ||
561 | } | ||
562 | continue; | ||
563 | } | ||
564 | } | ||
562 | } | 565 | } |
563 | continue; | 566 | *++p = *cf; |
564 | } | 567 | } while (*++cf); |
568 | |||
569 | if ((p == p0) || (*p != '/')) { /* not a trailing slash */ | ||
570 | ++p; /* so keep last character */ | ||
565 | } | 571 | } |
566 | } | 572 | *p = 0; |
567 | *++p = *cf; | 573 | sprintf(p0, "%s:%s", p0, c); |
568 | } while (*++cf); | 574 | } |
569 | |||
570 | if ((p == p0) || (*p != '/')) { /* not a trailing slash */ | ||
571 | ++p; /* so keep last character */ | ||
572 | } | ||
573 | *p = 0; | ||
574 | sprintf(p0, "%s:%s", p0, c); | ||
575 | } | ||
576 | #endif | 575 | #endif |
577 | 576 | ||
578 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR) | 577 | #if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR) |
579 | /* storing current config line */ | 578 | /* storing current config line */ |
580 | cur = calloc(1, sizeof(Htaccess) + strlen(p0)); | 579 | cur = calloc(1, sizeof(Htaccess) + strlen(p0)); |
581 | if(cur) { | 580 | if (cur) { |
582 | cf = strcpy(cur->before_colon, p0); | 581 | cf = strcpy(cur->before_colon, p0); |
583 | c = strchr(cf, ':'); | 582 | c = strchr(cf, ':'); |
584 | *c++ = 0; | 583 | *c++ = 0; |
585 | cur->after_colon = c; | 584 | cur->after_colon = c; |
586 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 585 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
587 | if(*cf == '.') { | 586 | if (*cf == '.') { |
588 | /* config .mime line move top for overwrite previous */ | 587 | /* config .mime line move top for overwrite previous */ |
589 | cur->next = config->mime_a; | 588 | cur->next = config->mime_a; |
590 | config->mime_a = cur; | 589 | config->mime_a = cur; |
591 | continue; | 590 | continue; |
592 | } | 591 | } |
593 | #endif | 592 | #endif |
594 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 593 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
595 | if(*cf == '*' && cf[1] == '.') { | 594 | if (*cf == '*' && cf[1] == '.') { |
596 | /* config script interpreter line move top for overwrite previous */ | 595 | /* config script interpreter line move top for overwrite previous */ |
597 | cur->next = config->script_i; | 596 | cur->next = config->script_i; |
598 | config->script_i = cur; | 597 | config->script_i = cur; |
599 | continue; | 598 | continue; |
600 | } | 599 | } |
601 | #endif | 600 | #endif |
602 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 601 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
603 | free(p0); | 602 | free(p0); |
604 | if(prev == NULL) { | 603 | if (prev == NULL) { |
605 | /* first line */ | 604 | /* first line */ |
606 | config->auth = prev = cur; | 605 | config->auth = prev = cur; |
607 | } else { | ||
608 | /* sort path, if current lenght eq or bigger then move up */ | ||
609 | Htaccess *prev_hti = config->auth; | ||
610 | size_t l = strlen(cf); | ||
611 | Htaccess *hti; | ||
612 | |||
613 | for(hti = prev_hti; hti; hti = hti->next) { | ||
614 | if(l >= strlen(hti->before_colon)) { | ||
615 | /* insert before hti */ | ||
616 | cur->next = hti; | ||
617 | if(prev_hti != hti) { | ||
618 | prev_hti->next = cur; | ||
619 | } else { | 606 | } else { |
620 | /* insert as top */ | 607 | /* sort path, if current lenght eq or bigger then move up */ |
621 | config->auth = cur; | 608 | Htaccess *prev_hti = config->auth; |
609 | size_t l = strlen(cf); | ||
610 | Htaccess *hti; | ||
611 | |||
612 | for (hti = prev_hti; hti; hti = hti->next) { | ||
613 | if (l >= strlen(hti->before_colon)) { | ||
614 | /* insert before hti */ | ||
615 | cur->next = hti; | ||
616 | if (prev_hti != hti) { | ||
617 | prev_hti->next = cur; | ||
618 | } else { | ||
619 | /* insert as top */ | ||
620 | config->auth = cur; | ||
621 | } | ||
622 | break; | ||
623 | } | ||
624 | if (prev_hti != hti) | ||
625 | prev_hti = prev_hti->next; | ||
626 | } | ||
627 | if (!hti) { /* not inserted, add to bottom */ | ||
628 | prev->next = cur; | ||
629 | prev = cur; | ||
630 | } | ||
622 | } | 631 | } |
623 | break; | ||
624 | } | ||
625 | if(prev_hti != hti) | ||
626 | prev_hti = prev_hti->next; | ||
627 | } | ||
628 | if(!hti) { /* not inserted, add to bottom */ | ||
629 | prev->next = cur; | ||
630 | prev = cur; | ||
631 | } | ||
632 | } | ||
633 | #endif | 632 | #endif |
634 | } | 633 | } |
635 | #endif | 634 | #endif |
636 | } | 635 | } |
637 | fclose(f); | 636 | fclose(f); |
638 | } | 637 | } |
639 | 638 | ||
640 | #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR | 639 | #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR |
@@ -657,21 +656,21 @@ static void parse_conf(const char *path, int flag) | |||
657 | ****************************************************************************/ | 656 | ****************************************************************************/ |
658 | static char *encodeString(const char *string) | 657 | static char *encodeString(const char *string) |
659 | { | 658 | { |
660 | /* take the simple route and encode everything */ | 659 | /* take the simple route and encode everything */ |
661 | /* could possibly scan once to get length. */ | 660 | /* could possibly scan once to get length. */ |
662 | int len = strlen(string); | 661 | int len = strlen(string); |
663 | char *out = malloc(len * 6 + 1); | 662 | char *out = malloc(len * 6 + 1); |
664 | char *p=out; | 663 | char *p = out; |
665 | char ch; | 664 | char ch; |
666 | 665 | ||
667 | if (!out) return ""; | 666 | if (!out) return ""; |
668 | while ((ch = *string++)) { | 667 | while ((ch = *string++)) { |
669 | // very simple check for what to encode | 668 | // very simple check for what to encode |
670 | if (isalnum(ch)) *p++ = ch; | 669 | if (isalnum(ch)) *p++ = ch; |
671 | else p += sprintf(p, "&#%d;", (unsigned char) ch); | 670 | else p += sprintf(p, "&#%d;", (unsigned char) ch); |
672 | } | 671 | } |
673 | *p=0; | 672 | *p = 0; |
674 | return out; | 673 | return out; |
675 | } | 674 | } |
676 | #endif /* CONFIG_FEATURE_HTTPD_ENCODE_URL_STR */ | 675 | #endif /* CONFIG_FEATURE_HTTPD_ENCODE_URL_STR */ |
677 | 676 | ||
@@ -696,34 +695,33 @@ static char *encodeString(const char *string) | |||
696 | ****************************************************************************/ | 695 | ****************************************************************************/ |
697 | static char *decodeString(char *orig, int flag_plus_to_space) | 696 | static char *decodeString(char *orig, int flag_plus_to_space) |
698 | { | 697 | { |
699 | /* note that decoded string is always shorter than original */ | 698 | /* note that decoded string is always shorter than original */ |
700 | char *string = orig; | 699 | char *string = orig; |
701 | char *ptr = string; | 700 | char *ptr = string; |
702 | 701 | ||
703 | while (*ptr) | 702 | while (*ptr) { |
704 | { | 703 | if (*ptr == '+' && flag_plus_to_space) { *string++ = ' '; ptr++; } |
705 | if (*ptr == '+' && flag_plus_to_space) { *string++ = ' '; ptr++; } | 704 | else if (*ptr != '%') *string++ = *ptr++; |
706 | else if (*ptr != '%') *string++ = *ptr++; | 705 | else { |
707 | else { | 706 | unsigned int value1, value2; |
708 | unsigned int value1, value2; | 707 | |
709 | 708 | ptr++; | |
710 | ptr++; | 709 | if (sscanf(ptr, "%1X", &value1) != 1 || |
711 | if(sscanf(ptr, "%1X", &value1) != 1 || | 710 | sscanf(ptr+1, "%1X", &value2) != 1) { |
712 | sscanf(ptr+1, "%1X", &value2) != 1) { | 711 | if (!flag_plus_to_space) |
713 | if(!flag_plus_to_space) | 712 | return NULL; |
714 | return NULL; | 713 | *string++ = '%'; |
715 | *string++ = '%'; | 714 | } else { |
716 | } else { | 715 | value1 = value1 * 16 + value2; |
717 | value1 = value1 * 16 + value2; | 716 | if (value1 == '/' || value1 == 0) |
718 | if(value1 == '/' || value1 == 0) | 717 | return orig+1; |
719 | return orig+1; | 718 | *string++ = value1; |
720 | *string++ = value1; | 719 | ptr += 2; |
721 | ptr += 2; | 720 | } |
722 | } | 721 | } |
723 | } | 722 | } |
724 | } | 723 | *string = '\0'; |
725 | *string = '\0'; | 724 | return orig; |
726 | return orig; | ||
727 | } | 725 | } |
728 | 726 | ||
729 | 727 | ||
@@ -747,29 +745,29 @@ static char *decodeString(char *orig, int flag_plus_to_space) | |||
747 | * | 745 | * |
748 | ****************************************************************************/ | 746 | ****************************************************************************/ |
749 | static void addEnv(const char *name_before_underline, | 747 | static void addEnv(const char *name_before_underline, |
750 | const char *name_after_underline, const char *value) | 748 | const char *name_after_underline, const char *value) |
751 | { | 749 | { |
752 | char *s = NULL; | 750 | char *s = NULL; |
753 | const char *underline; | 751 | const char *underline; |
754 | 752 | ||
755 | if (!value) | 753 | if (!value) |
756 | value = ""; | 754 | value = ""; |
757 | underline = *name_after_underline ? "_" : ""; | 755 | underline = *name_after_underline ? "_" : ""; |
758 | asprintf(&s, "%s%s%s=%s", name_before_underline, underline, | 756 | asprintf(&s, "%s%s%s=%s", name_before_underline, underline, |
759 | name_after_underline, value); | 757 | name_after_underline, value); |
760 | if(s) { | 758 | if (s) { |
761 | putenv(s); | 759 | putenv(s); |
762 | } | 760 | } |
763 | } | 761 | } |
764 | 762 | ||
765 | #if defined(CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV) || defined(CONFIG_FEATURE_HTTPD_WITHOUT_INETD) | 763 | #if defined(CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV) || defined(CONFIG_FEATURE_HTTPD_WITHOUT_INETD) |
766 | /* set environs SERVER_PORT and REMOTE_PORT */ | 764 | /* set environs SERVER_PORT and REMOTE_PORT */ |
767 | static void addEnvPort(const char *port_name) | 765 | static void addEnvPort(const char *port_name) |
768 | { | 766 | { |
769 | char buf[16]; | 767 | char buf[16]; |
770 | 768 | ||
771 | sprintf(buf, "%u", config->port); | 769 | sprintf(buf, "%u", config->port); |
772 | addEnv(port_name, "PORT", buf); | 770 | addEnv(port_name, "PORT", buf); |
773 | } | 771 | } |
774 | #endif | 772 | #endif |
775 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ | 773 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ |
@@ -797,39 +795,39 @@ static void addEnvPort(const char *port_name) | |||
797 | static void decodeBase64(char *Data) | 795 | static void decodeBase64(char *Data) |
798 | { | 796 | { |
799 | 797 | ||
800 | const unsigned char *in = (const unsigned char *)Data; | 798 | const unsigned char *in = (const unsigned char *)Data; |
801 | // The decoded size will be at most 3/4 the size of the encoded | 799 | // The decoded size will be at most 3/4 the size of the encoded |
802 | unsigned long ch = 0; | 800 | unsigned long ch = 0; |
803 | int i = 0; | 801 | int i = 0; |
804 | 802 | ||
805 | while (*in) { | 803 | while (*in) { |
806 | int t = *in++; | 804 | int t = *in++; |
807 | 805 | ||
808 | if(t >= '0' && t <= '9') | 806 | if (t >= '0' && t <= '9') |
809 | t = t - '0' + 52; | 807 | t = t - '0' + 52; |
810 | else if(t >= 'A' && t <= 'Z') | 808 | else if (t >= 'A' && t <= 'Z') |
811 | t = t - 'A'; | 809 | t = t - 'A'; |
812 | else if(t >= 'a' && t <= 'z') | 810 | else if (t >= 'a' && t <= 'z') |
813 | t = t - 'a' + 26; | 811 | t = t - 'a' + 26; |
814 | else if(t == '+') | 812 | else if (t == '+') |
815 | t = 62; | 813 | t = 62; |
816 | else if(t == '/') | 814 | else if (t == '/') |
817 | t = 63; | 815 | t = 63; |
818 | else if(t == '=') | 816 | else if (t == '=') |
819 | t = 0; | 817 | t = 0; |
820 | else | 818 | else |
821 | continue; | 819 | continue; |
822 | 820 | ||
823 | ch = (ch << 6) | t; | 821 | ch = (ch << 6) | t; |
824 | i++; | 822 | i++; |
825 | if (i == 4) { | 823 | if (i == 4) { |
826 | *Data++ = (char) (ch >> 16); | 824 | *Data++ = (char) (ch >> 16); |
827 | *Data++ = (char) (ch >> 8); | 825 | *Data++ = (char) (ch >> 8); |
828 | *Data++ = (char) ch; | 826 | *Data++ = (char) ch; |
829 | i = 0; | 827 | i = 0; |
830 | } | 828 | } |
831 | } | 829 | } |
832 | *Data = 0; | 830 | *Data = 0; |
833 | } | 831 | } |
834 | #endif | 832 | #endif |
835 | 833 | ||
@@ -848,28 +846,28 @@ static void decodeBase64(char *Data) | |||
848 | ****************************************************************************/ | 846 | ****************************************************************************/ |
849 | static int openServer(void) | 847 | static int openServer(void) |
850 | { | 848 | { |
851 | struct sockaddr_in lsocket; | 849 | struct sockaddr_in lsocket; |
852 | int fd; | 850 | int fd; |
853 | int on = 1; | 851 | int on = 1; |
854 | 852 | ||
855 | /* create the socket right now */ | 853 | /* create the socket right now */ |
856 | /* inet_addr() returns a value that is already in network order */ | 854 | /* inet_addr() returns a value that is already in network order */ |
857 | memset(&lsocket, 0, sizeof(lsocket)); | 855 | memset(&lsocket, 0, sizeof(lsocket)); |
858 | lsocket.sin_family = AF_INET; | 856 | lsocket.sin_family = AF_INET; |
859 | lsocket.sin_addr.s_addr = INADDR_ANY; | 857 | lsocket.sin_addr.s_addr = INADDR_ANY; |
860 | lsocket.sin_port = htons(config->port); | 858 | lsocket.sin_port = htons(config->port); |
861 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | 859 | fd = xsocket(AF_INET, SOCK_STREAM, 0); |
862 | /* tell the OS it's OK to reuse a previous address even though */ | 860 | /* tell the OS it's OK to reuse a previous address even though */ |
863 | /* it may still be in a close down state. Allows bind to succeed. */ | 861 | /* it may still be in a close down state. Allows bind to succeed. */ |
864 | #ifdef SO_REUSEPORT | 862 | #ifdef SO_REUSEPORT |
865 | setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) ; | 863 | setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) ; |
866 | #else | 864 | #else |
867 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) ; | 865 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) ; |
868 | #endif | 866 | #endif |
869 | xbind(fd, (struct sockaddr *)&lsocket, sizeof(lsocket)); | 867 | xbind(fd, (struct sockaddr *)&lsocket, sizeof(lsocket)); |
870 | xlisten(fd, 9); | 868 | xlisten(fd, 9); |
871 | signal(SIGCHLD, SIG_IGN); /* prevent zombie (defunct) processes */ | 869 | signal(SIGCHLD, SIG_IGN); /* prevent zombie (defunct) processes */ |
872 | return fd; | 870 | return fd; |
873 | } | 871 | } |
874 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ | 872 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ |
875 | 873 | ||
@@ -890,65 +888,65 @@ static int openServer(void) | |||
890 | ****************************************************************************/ | 888 | ****************************************************************************/ |
891 | static int sendHeaders(HttpResponseNum responseNum) | 889 | static int sendHeaders(HttpResponseNum responseNum) |
892 | { | 890 | { |
893 | char *buf = config->buf; | 891 | char *buf = config->buf; |
894 | const char *responseString = ""; | 892 | const char *responseString = ""; |
895 | const char *infoString = 0; | 893 | const char *infoString = 0; |
896 | const char *mime_type; | 894 | const char *mime_type; |
897 | unsigned int i; | 895 | unsigned int i; |
898 | time_t timer = time(0); | 896 | time_t timer = time(0); |
899 | char timeStr[80]; | 897 | char timeStr[80]; |
900 | int len; | 898 | int len; |
901 | 899 | ||
902 | for (i = 0; | 900 | for (i = 0; |
903 | i < (sizeof(httpResponseNames)/sizeof(httpResponseNames[0])); i++) { | 901 | i < (sizeof(httpResponseNames)/sizeof(httpResponseNames[0])); i++) { |
904 | if (httpResponseNames[i].type == responseNum) { | 902 | if (httpResponseNames[i].type == responseNum) { |
905 | responseString = httpResponseNames[i].name; | 903 | responseString = httpResponseNames[i].name; |
906 | infoString = httpResponseNames[i].info; | 904 | infoString = httpResponseNames[i].info; |
907 | break; | 905 | break; |
908 | } | 906 | } |
909 | } | 907 | } |
910 | /* error message is HTML */ | 908 | /* error message is HTML */ |
911 | mime_type = responseNum == HTTP_OK ? | 909 | mime_type = responseNum == HTTP_OK ? |
912 | config->httpd_found.found_mime_type : "text/html"; | 910 | config->httpd_found.found_mime_type : "text/html"; |
913 | 911 | ||
914 | /* emit the current date */ | 912 | /* emit the current date */ |
915 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); | 913 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer)); |
916 | len = sprintf(buf, | 914 | len = sprintf(buf, |
917 | "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" | 915 | "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" |
918 | "Date: %s\r\nConnection: close\r\n", | 916 | "Date: %s\r\nConnection: close\r\n", |
919 | responseNum, responseString, mime_type, timeStr); | 917 | responseNum, responseString, mime_type, timeStr); |
920 | 918 | ||
921 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 919 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
922 | if (responseNum == HTTP_UNAUTHORIZED) { | 920 | if (responseNum == HTTP_UNAUTHORIZED) { |
923 | len += sprintf(buf+len, "WWW-Authenticate: Basic realm=\"%s\"\r\n", | 921 | len += sprintf(buf+len, "WWW-Authenticate: Basic realm=\"%s\"\r\n", |
924 | config->realm); | 922 | config->realm); |
925 | } | 923 | } |
926 | #endif | 924 | #endif |
927 | if(responseNum == HTTP_MOVED_TEMPORARILY) { | 925 | if (responseNum == HTTP_MOVED_TEMPORARILY) { |
928 | len += sprintf(buf+len, "Location: %s/%s%s\r\n", | 926 | len += sprintf(buf+len, "Location: %s/%s%s\r\n", |
929 | config->httpd_found.found_moved_temporarily, | 927 | config->httpd_found.found_moved_temporarily, |
930 | (config->query ? "?" : ""), | 928 | (config->query ? "?" : ""), |
931 | (config->query ? config->query : "")); | 929 | (config->query ? config->query : "")); |
932 | } | 930 | } |
933 | 931 | ||
934 | if (config->ContentLength != -1) { /* file */ | 932 | if (config->ContentLength != -1) { /* file */ |
935 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); | 933 | strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); |
936 | len += sprintf(buf+len, "Last-Modified: %s\r\n%s " cont_l_fmt "\r\n", | 934 | len += sprintf(buf+len, "Last-Modified: %s\r\n%s " cont_l_fmt "\r\n", |
937 | timeStr, Content_length, cont_l_type config->ContentLength); | 935 | timeStr, Content_length, cont_l_type config->ContentLength); |
938 | } | 936 | } |
939 | strcat(buf, "\r\n"); | 937 | strcat(buf, "\r\n"); |
940 | len += 2; | 938 | len += 2; |
941 | if (infoString) { | 939 | if (infoString) { |
942 | len += sprintf(buf+len, | 940 | len += sprintf(buf+len, |
943 | "<HEAD><TITLE>%d %s</TITLE></HEAD>\n" | 941 | "<HEAD><TITLE>%d %s</TITLE></HEAD>\n" |
944 | "<BODY><H1>%d %s</H1>\n%s\n</BODY>\n", | 942 | "<BODY><H1>%d %s</H1>\n%s\n</BODY>\n", |
945 | responseNum, responseString, | 943 | responseNum, responseString, |
946 | responseNum, responseString, infoString); | 944 | responseNum, responseString, infoString); |
947 | } | 945 | } |
948 | #if DEBUG | 946 | #if DEBUG |
949 | fprintf(stderr, "Headers: '%s'", buf); | 947 | fprintf(stderr, "Headers: '%s'", buf); |
950 | #endif | 948 | #endif |
951 | return full_write(a_c_w, buf, len); | 949 | return full_write(a_c_w, buf, len); |
952 | } | 950 | } |
953 | 951 | ||
954 | /**************************************************************************** | 952 | /**************************************************************************** |
@@ -964,20 +962,20 @@ static int sendHeaders(HttpResponseNum responseNum) | |||
964 | ****************************************************************************/ | 962 | ****************************************************************************/ |
965 | static int getLine(void) | 963 | static int getLine(void) |
966 | { | 964 | { |
967 | int count = 0; | 965 | int count = 0; |
968 | char *buf = config->buf; | 966 | char *buf = config->buf; |
969 | 967 | ||
970 | while (read(a_c_r, buf + count, 1) == 1) { | 968 | while (read(a_c_r, buf + count, 1) == 1) { |
971 | if (buf[count] == '\r') continue; | 969 | if (buf[count] == '\r') continue; |
972 | if (buf[count] == '\n') { | 970 | if (buf[count] == '\n') { |
973 | buf[count] = 0; | 971 | buf[count] = 0; |
974 | return count; | 972 | return count; |
975 | } | 973 | } |
976 | if(count < (MAX_MEMORY_BUFF-1)) /* check owerflow */ | 974 | if (count < (MAX_MEMORY_BUFF-1)) /* check owerflow */ |
977 | count++; | 975 | count++; |
978 | } | 976 | } |
979 | if (count) return count; | 977 | if (count) return count; |
980 | else return -1; | 978 | else return -1; |
981 | } | 979 | } |
982 | 980 | ||
983 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 981 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
@@ -1004,233 +1002,233 @@ static int getLine(void) | |||
1004 | * | 1002 | * |
1005 | ****************************************************************************/ | 1003 | ****************************************************************************/ |
1006 | static int sendCgi(const char *url, | 1004 | static int sendCgi(const char *url, |
1007 | const char *request, int bodyLen, const char *cookie, | 1005 | const char *request, int bodyLen, const char *cookie, |
1008 | const char *content_type) | 1006 | const char *content_type) |
1009 | { | 1007 | { |
1010 | int fromCgi[2]; /* pipe for reading data from CGI */ | 1008 | int fromCgi[2]; /* pipe for reading data from CGI */ |
1011 | int toCgi[2]; /* pipe for sending data to CGI */ | 1009 | int toCgi[2]; /* pipe for sending data to CGI */ |
1012 | |||
1013 | static char * argp[] = { 0, 0 }; | ||
1014 | int pid = 0; | ||
1015 | int inFd; | ||
1016 | int outFd; | ||
1017 | int firstLine = 1; | ||
1018 | |||
1019 | do { | ||
1020 | if (pipe(fromCgi) != 0) { | ||
1021 | break; | ||
1022 | } | ||
1023 | if (pipe(toCgi) != 0) { | ||
1024 | break; | ||
1025 | } | ||
1026 | |||
1027 | pid = fork(); | ||
1028 | if (pid < 0) { | ||
1029 | pid = 0; | ||
1030 | break; | ||
1031 | } | ||
1032 | |||
1033 | if (!pid) { | ||
1034 | /* child process */ | ||
1035 | char *script; | ||
1036 | char *purl = strdup( url ); | ||
1037 | char realpath_buff[MAXPATHLEN]; | ||
1038 | |||
1039 | if(purl == NULL) | ||
1040 | _exit(242); | ||
1041 | |||
1042 | inFd = toCgi[0]; | ||
1043 | outFd = fromCgi[1]; | ||
1044 | |||
1045 | dup2(inFd, 0); // replace stdin with the pipe | ||
1046 | dup2(outFd, 1); // replace stdout with the pipe | ||
1047 | if(!DEBUG) | ||
1048 | dup2(outFd, 2); // replace stderr with the pipe | ||
1049 | |||
1050 | close(toCgi[0]); | ||
1051 | close(toCgi[1]); | ||
1052 | close(fromCgi[0]); | ||
1053 | close(fromCgi[1]); | ||
1054 | |||
1055 | /* | ||
1056 | * Find PATH_INFO. | ||
1057 | */ | ||
1058 | script = purl; | ||
1059 | while((script = strchr( script + 1, '/' )) != NULL) { | ||
1060 | /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */ | ||
1061 | struct stat sb; | ||
1062 | 1010 | ||
1063 | *script = '\0'; | 1011 | static char * argp[] = { 0, 0 }; |
1064 | if(is_directory(purl + 1, 1, &sb) == 0) { | 1012 | int pid = 0; |
1065 | /* not directory, found script.cgi/PATH_INFO */ | 1013 | int inFd; |
1066 | *script = '/'; | 1014 | int outFd; |
1067 | break; | 1015 | int firstLine = 1; |
1068 | } | 1016 | |
1069 | *script = '/'; /* is directory, find next '/' */ | 1017 | do { |
1070 | } | 1018 | if (pipe(fromCgi) != 0) { |
1071 | addEnv("PATH", "INFO", script); /* set /PATH_INFO or NULL */ | 1019 | break; |
1072 | addEnv("PATH", "", getenv("PATH")); | 1020 | } |
1073 | addEnv("REQUEST", "METHOD", request); | 1021 | if (pipe(toCgi) != 0) { |
1074 | if(config->query) { | 1022 | break; |
1075 | char *uri = alloca(strlen(purl) + 2 + strlen(config->query)); | 1023 | } |
1076 | if(uri) | 1024 | |
1077 | sprintf(uri, "%s?%s", purl, config->query); | 1025 | pid = fork(); |
1078 | addEnv("REQUEST", "URI", uri); | 1026 | if (pid < 0) { |
1079 | } else { | 1027 | pid = 0; |
1080 | addEnv("REQUEST", "URI", purl); | 1028 | break; |
1081 | } | 1029 | } |
1082 | if(script != NULL) | 1030 | |
1083 | *script = '\0'; /* reduce /PATH_INFO */ | 1031 | if (!pid) { |
1084 | /* SCRIPT_FILENAME required by PHP in CGI mode */ | 1032 | /* child process */ |
1085 | if(realpath(purl + 1, realpath_buff)) | 1033 | char *script; |
1086 | addEnv("SCRIPT", "FILENAME", realpath_buff); | 1034 | char *purl = strdup(url); |
1087 | else | 1035 | char realpath_buff[MAXPATHLEN]; |
1088 | *realpath_buff = 0; | 1036 | |
1089 | /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ | 1037 | if (purl == NULL) |
1090 | addEnv("SCRIPT_NAME", "", purl); | 1038 | _exit(242); |
1091 | addEnv("QUERY_STRING", "", config->query); | 1039 | |
1092 | addEnv("SERVER", "SOFTWARE", httpdVersion); | 1040 | inFd = toCgi[0]; |
1093 | addEnv("SERVER", "PROTOCOL", "HTTP/1.0"); | 1041 | outFd = fromCgi[1]; |
1094 | addEnv("GATEWAY_INTERFACE", "", "CGI/1.1"); | 1042 | |
1095 | addEnv("REMOTE", "ADDR", config->rmt_ip_str); | 1043 | dup2(inFd, 0); // replace stdin with the pipe |
1096 | #ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | 1044 | dup2(outFd, 1); // replace stdout with the pipe |
1097 | addEnvPort("REMOTE"); | 1045 | if (!DEBUG) |
1098 | #endif | 1046 | dup2(outFd, 2); // replace stderr with the pipe |
1099 | if(bodyLen) { | 1047 | |
1100 | char sbl[32]; | 1048 | close(toCgi[0]); |
1101 | 1049 | close(toCgi[1]); | |
1102 | sprintf(sbl, "%d", bodyLen); | 1050 | close(fromCgi[0]); |
1103 | addEnv("CONTENT", "LENGTH", sbl); | 1051 | close(fromCgi[1]); |
1104 | } | 1052 | |
1105 | if(cookie) | 1053 | /* |
1106 | addEnv("HTTP", "COOKIE", cookie); | 1054 | * Find PATH_INFO. |
1107 | if(content_type) | 1055 | */ |
1108 | addEnv("CONTENT", "TYPE", content_type); | 1056 | script = purl; |
1109 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1057 | while ((script = strchr(script + 1, '/')) != NULL) { |
1110 | if(config->remoteuser) { | 1058 | /* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */ |
1111 | addEnv("REMOTE", "USER", config->remoteuser); | 1059 | struct stat sb; |
1112 | addEnv("AUTH_TYPE", "", "Basic"); | 1060 | |
1113 | } | 1061 | *script = '\0'; |
1114 | #endif | 1062 | if (is_directory(purl + 1, 1, &sb) == 0) { |
1115 | if(config->referer) | 1063 | /* not directory, found script.cgi/PATH_INFO */ |
1116 | addEnv("HTTP", "REFERER", config->referer); | 1064 | *script = '/'; |
1117 | |||
1118 | /* set execve argp[0] without path */ | ||
1119 | argp[0] = strrchr( purl, '/' ) + 1; | ||
1120 | /* but script argp[0] must have absolute path and chdiring to this */ | ||
1121 | if(*realpath_buff) { | ||
1122 | script = strrchr(realpath_buff, '/'); | ||
1123 | if(script) { | ||
1124 | *script = '\0'; | ||
1125 | if(chdir(realpath_buff) == 0) { | ||
1126 | // now run the program. If it fails, | ||
1127 | // use _exit() so no destructors | ||
1128 | // get called and make a mess. | ||
1129 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
1130 | char *interpr = NULL; | ||
1131 | char *suffix = strrchr(purl, '.'); | ||
1132 | |||
1133 | if(suffix) { | ||
1134 | Htaccess * cur; | ||
1135 | for (cur = config->script_i; cur; cur = cur->next) | ||
1136 | if(strcmp(cur->before_colon + 1, suffix) == 0) { | ||
1137 | interpr = cur->after_colon; | ||
1138 | break; | 1065 | break; |
1139 | } | 1066 | } |
1140 | } | 1067 | *script = '/'; /* is directory, find next '/' */ |
1068 | } | ||
1069 | addEnv("PATH", "INFO", script); /* set /PATH_INFO or NULL */ | ||
1070 | addEnv("PATH", "", getenv("PATH")); | ||
1071 | addEnv("REQUEST", "METHOD", request); | ||
1072 | if (config->query) { | ||
1073 | char *uri = alloca(strlen(purl) + 2 + strlen(config->query)); | ||
1074 | if (uri) | ||
1075 | sprintf(uri, "%s?%s", purl, config->query); | ||
1076 | addEnv("REQUEST", "URI", uri); | ||
1077 | } else { | ||
1078 | addEnv("REQUEST", "URI", purl); | ||
1079 | } | ||
1080 | if (script != NULL) | ||
1081 | *script = '\0'; /* reduce /PATH_INFO */ | ||
1082 | /* SCRIPT_FILENAME required by PHP in CGI mode */ | ||
1083 | if (realpath(purl + 1, realpath_buff)) | ||
1084 | addEnv("SCRIPT", "FILENAME", realpath_buff); | ||
1085 | else | ||
1086 | *realpath_buff = 0; | ||
1087 | /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */ | ||
1088 | addEnv("SCRIPT_NAME", "", purl); | ||
1089 | addEnv("QUERY_STRING", "", config->query); | ||
1090 | addEnv("SERVER", "SOFTWARE", httpdVersion); | ||
1091 | addEnv("SERVER", "PROTOCOL", "HTTP/1.0"); | ||
1092 | addEnv("GATEWAY_INTERFACE", "", "CGI/1.1"); | ||
1093 | addEnv("REMOTE", "ADDR", config->rmt_ip_str); | ||
1094 | #ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV | ||
1095 | addEnvPort("REMOTE"); | ||
1096 | #endif | ||
1097 | if (bodyLen) { | ||
1098 | char sbl[32]; | ||
1099 | |||
1100 | sprintf(sbl, "%d", bodyLen); | ||
1101 | addEnv("CONTENT", "LENGTH", sbl); | ||
1102 | } | ||
1103 | if (cookie) | ||
1104 | addEnv("HTTP", "COOKIE", cookie); | ||
1105 | if (content_type) | ||
1106 | addEnv("CONTENT", "TYPE", content_type); | ||
1107 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | ||
1108 | if (config->remoteuser) { | ||
1109 | addEnv("REMOTE", "USER", config->remoteuser); | ||
1110 | addEnv("AUTH_TYPE", "", "Basic"); | ||
1111 | } | ||
1141 | #endif | 1112 | #endif |
1142 | *script = '/'; | 1113 | if (config->referer) |
1114 | addEnv("HTTP", "REFERER", config->referer); | ||
1115 | |||
1116 | /* set execve argp[0] without path */ | ||
1117 | argp[0] = strrchr(purl, '/') + 1; | ||
1118 | /* but script argp[0] must have absolute path and chdiring to this */ | ||
1119 | if (*realpath_buff) { | ||
1120 | script = strrchr(realpath_buff, '/'); | ||
1121 | if (script) { | ||
1122 | *script = '\0'; | ||
1123 | if (chdir(realpath_buff) == 0) { | ||
1124 | // now run the program. If it fails, | ||
1125 | // use _exit() so no destructors | ||
1126 | // get called and make a mess. | ||
1143 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 1127 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
1144 | if (interpr) | 1128 | char *interpr = NULL; |
1145 | execv(interpr, argp); | 1129 | char *suffix = strrchr(purl, '.'); |
1146 | else | 1130 | |
1131 | if (suffix) { | ||
1132 | Htaccess * cur; | ||
1133 | for (cur = config->script_i; cur; cur = cur->next) | ||
1134 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | ||
1135 | interpr = cur->after_colon; | ||
1136 | break; | ||
1137 | } | ||
1138 | } | ||
1139 | #endif | ||
1140 | *script = '/'; | ||
1141 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
1142 | if (interpr) | ||
1143 | execv(interpr, argp); | ||
1144 | else | ||
1147 | #endif | 1145 | #endif |
1148 | execv(realpath_buff, argp); | 1146 | execv(realpath_buff, argp); |
1149 | } | 1147 | } |
1150 | } | 1148 | } |
1151 | } | 1149 | } |
1152 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1150 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1153 | config->accepted_socket = 1; /* send to stdout */ | 1151 | config->accepted_socket = 1; /* send to stdout */ |
1154 | #endif | 1152 | #endif |
1155 | sendHeaders(HTTP_NOT_FOUND); | 1153 | sendHeaders(HTTP_NOT_FOUND); |
1156 | _exit(242); | 1154 | _exit(242); |
1157 | } /* end child */ | 1155 | } /* end child */ |
1158 | 1156 | ||
1159 | } while (0); | 1157 | } while (0); |
1160 | 1158 | ||
1161 | if (pid) { | 1159 | if (pid) { |
1162 | /* parent process */ | 1160 | /* parent process */ |
1163 | int status; | 1161 | int status; |
1164 | size_t post_readed_size = 0, post_readed_idx = 0; | 1162 | size_t post_readed_size = 0, post_readed_idx = 0; |
1165 | 1163 | ||
1166 | inFd = fromCgi[0]; | 1164 | inFd = fromCgi[0]; |
1167 | outFd = toCgi[1]; | 1165 | outFd = toCgi[1]; |
1168 | close(fromCgi[1]); | 1166 | close(fromCgi[1]); |
1169 | close(toCgi[0]); | 1167 | close(toCgi[0]); |
1170 | signal(SIGPIPE, SIG_IGN); | 1168 | signal(SIGPIPE, SIG_IGN); |
1171 | 1169 | ||
1172 | while (1) { | 1170 | while (1) { |
1173 | fd_set readSet; | 1171 | fd_set readSet; |
1174 | fd_set writeSet; | 1172 | fd_set writeSet; |
1175 | char wbuf[128]; | 1173 | char wbuf[128]; |
1176 | int nfound; | 1174 | int nfound; |
1177 | int count; | 1175 | int count; |
1178 | 1176 | ||
1179 | FD_ZERO(&readSet); | 1177 | FD_ZERO(&readSet); |
1180 | FD_ZERO(&writeSet); | 1178 | FD_ZERO(&writeSet); |
1181 | FD_SET(inFd, &readSet); | 1179 | FD_SET(inFd, &readSet); |
1182 | if(bodyLen > 0 || post_readed_size > 0) { | 1180 | if (bodyLen > 0 || post_readed_size > 0) { |
1183 | FD_SET(outFd, &writeSet); | 1181 | FD_SET(outFd, &writeSet); |
1184 | nfound = outFd > inFd ? outFd : inFd; | 1182 | nfound = outFd > inFd ? outFd : inFd; |
1185 | if(post_readed_size == 0) { | 1183 | if (post_readed_size == 0) { |
1186 | FD_SET(a_c_r, &readSet); | 1184 | FD_SET(a_c_r, &readSet); |
1187 | if(nfound < a_c_r) | 1185 | if (nfound < a_c_r) |
1188 | nfound = a_c_r; | 1186 | nfound = a_c_r; |
1189 | } | 1187 | } |
1190 | /* Now wait on the set of sockets! */ | 1188 | /* Now wait on the set of sockets! */ |
1191 | nfound = select(nfound + 1, &readSet, &writeSet, 0, NULL); | 1189 | nfound = select(nfound + 1, &readSet, &writeSet, 0, NULL); |
1192 | } else { | 1190 | } else { |
1193 | if(!bodyLen) { | 1191 | if (!bodyLen) { |
1194 | close(outFd); | 1192 | close(outFd); |
1195 | bodyLen = -1; | 1193 | bodyLen = -1; |
1196 | } | 1194 | } |
1197 | nfound = select(inFd + 1, &readSet, 0, 0, NULL); | 1195 | nfound = select(inFd + 1, &readSet, 0, 0, NULL); |
1198 | } | 1196 | } |
1199 | 1197 | ||
1200 | if (nfound <= 0) { | 1198 | if (nfound <= 0) { |
1201 | if (waitpid(pid, &status, WNOHANG) > 0) { | 1199 | if (waitpid(pid, &status, WNOHANG) > 0) { |
1202 | close(inFd); | 1200 | close(inFd); |
1203 | #if DEBUG | 1201 | #if DEBUG |
1204 | if (WIFEXITED(status)) | 1202 | if (WIFEXITED(status)) |
1205 | bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status)); | 1203 | bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status)); |
1206 | if (WIFSIGNALED(status)) | 1204 | if (WIFSIGNALED(status)) |
1207 | bb_error_msg("piped has exited with signal=%d", WTERMSIG(status)); | 1205 | bb_error_msg("piped has exited with signal=%d", WTERMSIG(status)); |
1208 | #endif | 1206 | #endif |
1209 | break; | 1207 | break; |
1210 | } | 1208 | } |
1211 | } else if(post_readed_size > 0 && FD_ISSET(outFd, &writeSet)) { | 1209 | } else if (post_readed_size > 0 && FD_ISSET(outFd, &writeSet)) { |
1212 | count = full_write(outFd, wbuf + post_readed_idx, post_readed_size); | 1210 | count = full_write(outFd, wbuf + post_readed_idx, post_readed_size); |
1213 | if(count > 0) { | 1211 | if (count > 0) { |
1214 | post_readed_size -= count; | 1212 | post_readed_size -= count; |
1215 | post_readed_idx += count; | 1213 | post_readed_idx += count; |
1216 | if(post_readed_size == 0) | 1214 | if (post_readed_size == 0) |
1217 | post_readed_idx = 0; | 1215 | post_readed_idx = 0; |
1218 | } else { | 1216 | } else { |
1219 | post_readed_size = post_readed_idx = bodyLen = 0; /* broken pipe to CGI */ | 1217 | post_readed_size = post_readed_idx = bodyLen = 0; /* broken pipe to CGI */ |
1220 | } | 1218 | } |
1221 | } else if(bodyLen > 0 && post_readed_size == 0 && FD_ISSET(a_c_r, &readSet)) { | 1219 | } else if (bodyLen > 0 && post_readed_size == 0 && FD_ISSET(a_c_r, &readSet)) { |
1222 | count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; | 1220 | count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen; |
1223 | count = safe_read(a_c_r, wbuf, count); | 1221 | count = safe_read(a_c_r, wbuf, count); |
1224 | if(count > 0) { | 1222 | if (count > 0) { |
1225 | post_readed_size += count; | 1223 | post_readed_size += count; |
1226 | bodyLen -= count; | 1224 | bodyLen -= count; |
1227 | } else { | 1225 | } else { |
1228 | bodyLen = 0; /* closed */ | 1226 | bodyLen = 0; /* closed */ |
1229 | } | 1227 | } |
1230 | } | 1228 | } |
1231 | if(FD_ISSET(inFd, &readSet)) { | 1229 | if (FD_ISSET(inFd, &readSet)) { |
1232 | int s = a_c_w; | 1230 | int s = a_c_w; |
1233 | char *rbuf = config->buf; | 1231 | char *rbuf = config->buf; |
1234 | 1232 | ||
1235 | #ifndef PIPE_BUF | 1233 | #ifndef PIPE_BUF |
1236 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ | 1234 | # define PIPESIZE 4096 /* amount of buffering in a pipe */ |
@@ -1241,33 +1239,33 @@ static int sendCgi(const char *url, | |||
1241 | # error "PIPESIZE >= MAX_MEMORY_BUFF" | 1239 | # error "PIPESIZE >= MAX_MEMORY_BUFF" |
1242 | #endif | 1240 | #endif |
1243 | 1241 | ||
1244 | // There is something to read | 1242 | // There is something to read |
1245 | count = safe_read(inFd, rbuf, PIPESIZE); | 1243 | count = safe_read(inFd, rbuf, PIPESIZE); |
1246 | if (count == 0) | 1244 | if (count == 0) |
1247 | break; /* closed */ | 1245 | break; /* closed */ |
1248 | if (count > 0) { | 1246 | if (count > 0) { |
1249 | if (firstLine) { | 1247 | if (firstLine) { |
1250 | rbuf[count] = 0; | 1248 | rbuf[count] = 0; |
1251 | /* check to see if the user script added headers */ | 1249 | /* check to see if the user script added headers */ |
1252 | if(strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) { | 1250 | if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) { |
1253 | full_write(s, "HTTP/1.0 200 OK\r\n", 17); | 1251 | full_write(s, "HTTP/1.0 200 OK\r\n", 17); |
1254 | } | 1252 | } |
1255 | if (strstr(rbuf, "ontent-") == 0) { | 1253 | if (strstr(rbuf, "ontent-") == 0) { |
1256 | full_write(s, "Content-type: text/plain\r\n\r\n", 28); | 1254 | full_write(s, "Content-type: text/plain\r\n\r\n", 28); |
1257 | } | 1255 | } |
1258 | firstLine = 0; | 1256 | firstLine = 0; |
1259 | } | 1257 | } |
1260 | if (full_write(s, rbuf, count) != count) | 1258 | if (full_write(s, rbuf, count) != count) |
1261 | break; | 1259 | break; |
1262 | 1260 | ||
1263 | #if DEBUG | 1261 | #if DEBUG |
1264 | fprintf(stderr, "cgi read %d bytes\n", count); | 1262 | fprintf(stderr, "cgi read %d bytes\n", count); |
1265 | #endif | 1263 | #endif |
1264 | } | ||
1265 | } | ||
1266 | } | ||
1266 | } | 1267 | } |
1267 | } | 1268 | return 0; |
1268 | } | ||
1269 | } | ||
1270 | return 0; | ||
1271 | } | 1269 | } |
1272 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ | 1270 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ |
1273 | 1271 | ||
@@ -1285,84 +1283,84 @@ static int sendCgi(const char *url, | |||
1285 | ****************************************************************************/ | 1283 | ****************************************************************************/ |
1286 | static int sendFile(const char *url) | 1284 | static int sendFile(const char *url) |
1287 | { | 1285 | { |
1288 | char * suffix; | 1286 | char * suffix; |
1289 | int f; | 1287 | int f; |
1290 | const char * const * table; | 1288 | const char * const * table; |
1291 | const char * try_suffix; | 1289 | const char * try_suffix; |
1292 | 1290 | ||
1293 | suffix = strrchr(url, '.'); | 1291 | suffix = strrchr(url, '.'); |
1294 | 1292 | ||
1295 | for (table = suffixTable; *table; table += 2) | 1293 | for (table = suffixTable; *table; table += 2) |
1296 | if(suffix != NULL && (try_suffix = strstr(*table, suffix)) != 0) { | 1294 | if (suffix != NULL && (try_suffix = strstr(*table, suffix)) != 0) { |
1297 | try_suffix += strlen(suffix); | 1295 | try_suffix += strlen(suffix); |
1298 | if(*try_suffix == 0 || *try_suffix == '.') | 1296 | if (*try_suffix == 0 || *try_suffix == '.') |
1299 | break; | 1297 | break; |
1300 | } | 1298 | } |
1301 | /* also, if not found, set default as "application/octet-stream"; */ | 1299 | /* also, if not found, set default as "application/octet-stream"; */ |
1302 | config->httpd_found.found_mime_type = *(table+1); | 1300 | config->httpd_found.found_mime_type = *(table+1); |
1303 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES | 1301 | #ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES |
1304 | if (suffix) { | 1302 | if (suffix) { |
1305 | Htaccess * cur; | 1303 | Htaccess * cur; |
1306 | 1304 | ||
1307 | for (cur = config->mime_a; cur; cur = cur->next) { | 1305 | for (cur = config->mime_a; cur; cur = cur->next) { |
1308 | if(strcmp(cur->before_colon, suffix) == 0) { | 1306 | if (strcmp(cur->before_colon, suffix) == 0) { |
1309 | config->httpd_found.found_mime_type = cur->after_colon; | 1307 | config->httpd_found.found_mime_type = cur->after_colon; |
1310 | break; | 1308 | break; |
1309 | } | ||
1310 | } | ||
1311 | } | 1311 | } |
1312 | } | ||
1313 | } | ||
1314 | #endif /* CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES */ | 1312 | #endif /* CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES */ |
1315 | 1313 | ||
1316 | #if DEBUG | 1314 | #if DEBUG |
1317 | fprintf(stderr, "Sending file '%s' Content-type: %s\n", | 1315 | fprintf(stderr, "Sending file '%s' Content-type: %s\n", |
1318 | url, config->httpd_found.found_mime_type); | 1316 | url, config->httpd_found.found_mime_type); |
1319 | #endif | 1317 | #endif |
1320 | 1318 | ||
1321 | f = open(url, O_RDONLY); | 1319 | f = open(url, O_RDONLY); |
1322 | if (f >= 0) { | 1320 | if (f >= 0) { |
1323 | int count; | 1321 | int count; |
1324 | char *buf = config->buf; | 1322 | char *buf = config->buf; |
1325 | 1323 | ||
1326 | sendHeaders(HTTP_OK); | 1324 | sendHeaders(HTTP_OK); |
1327 | while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { | 1325 | while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { |
1328 | if (full_write(a_c_w, buf, count) != count) | 1326 | if (full_write(a_c_w, buf, count) != count) |
1329 | break; | 1327 | break; |
1330 | } | 1328 | } |
1331 | close(f); | 1329 | close(f); |
1332 | } else { | 1330 | } else { |
1333 | #if DEBUG | 1331 | #if DEBUG |
1334 | bb_perror_msg("Unable to open '%s'", url); | 1332 | bb_perror_msg("Unable to open '%s'", url); |
1335 | #endif | 1333 | #endif |
1336 | sendHeaders(HTTP_NOT_FOUND); | 1334 | sendHeaders(HTTP_NOT_FOUND); |
1337 | } | 1335 | } |
1338 | 1336 | ||
1339 | return 0; | 1337 | return 0; |
1340 | } | 1338 | } |
1341 | 1339 | ||
1342 | static int checkPermIP(void) | 1340 | static int checkPermIP(void) |
1343 | { | 1341 | { |
1344 | Htaccess_IP * cur; | 1342 | Htaccess_IP * cur; |
1345 | 1343 | ||
1346 | /* This could stand some work */ | 1344 | /* This could stand some work */ |
1347 | for (cur = config->ip_a_d; cur; cur = cur->next) { | 1345 | for (cur = config->ip_a_d; cur; cur = cur->next) { |
1348 | #if DEBUG | 1346 | #if DEBUG |
1349 | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); | 1347 | fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str); |
1350 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", | 1348 | fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n", |
1351 | (unsigned char)(cur->ip >> 24), | 1349 | (unsigned char)(cur->ip >> 24), |
1352 | (unsigned char)(cur->ip >> 16), | 1350 | (unsigned char)(cur->ip >> 16), |
1353 | (unsigned char)(cur->ip >> 8), | 1351 | (unsigned char)(cur->ip >> 8), |
1354 | cur->ip & 0xff, | 1352 | cur->ip & 0xff, |
1355 | (unsigned char)(cur->mask >> 24), | 1353 | (unsigned char)(cur->mask >> 24), |
1356 | (unsigned char)(cur->mask >> 16), | 1354 | (unsigned char)(cur->mask >> 16), |
1357 | (unsigned char)(cur->mask >> 8), | 1355 | (unsigned char)(cur->mask >> 8), |
1358 | cur->mask & 0xff); | 1356 | cur->mask & 0xff); |
1359 | #endif | 1357 | #endif |
1360 | if((config->rmt_ip & cur->mask) == cur->ip) | 1358 | if ((config->rmt_ip & cur->mask) == cur->ip) |
1361 | return cur->allow_deny == 'A'; /* Allow/Deny */ | 1359 | return cur->allow_deny == 'A'; /* Allow/Deny */ |
1362 | } | 1360 | } |
1363 | 1361 | ||
1364 | /* if unconfigured, return 1 - access from all */ | 1362 | /* if unconfigured, return 1 - access from all */ |
1365 | return !config->flg_deny_all; | 1363 | return !config->flg_deny_all; |
1366 | } | 1364 | } |
1367 | 1365 | ||
1368 | /**************************************************************************** | 1366 | /**************************************************************************** |
@@ -1385,72 +1383,72 @@ static int checkPermIP(void) | |||
1385 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1383 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1386 | static int checkPerm(const char *path, const char *request) | 1384 | static int checkPerm(const char *path, const char *request) |
1387 | { | 1385 | { |
1388 | Htaccess * cur; | 1386 | Htaccess * cur; |
1389 | const char *p; | 1387 | const char *p; |
1390 | const char *p0; | 1388 | const char *p0; |
1391 | 1389 | ||
1392 | const char *prev = NULL; | 1390 | const char *prev = NULL; |
1393 | 1391 | ||
1394 | /* This could stand some work */ | 1392 | /* This could stand some work */ |
1395 | for (cur = config->auth; cur; cur = cur->next) { | 1393 | for (cur = config->auth; cur; cur = cur->next) { |
1396 | p0 = cur->before_colon; | 1394 | p0 = cur->before_colon; |
1397 | if(prev != NULL && strcmp(prev, p0) != 0) | 1395 | if (prev != NULL && strcmp(prev, p0) != 0) |
1398 | continue; /* find next identical */ | 1396 | continue; /* find next identical */ |
1399 | p = cur->after_colon; | 1397 | p = cur->after_colon; |
1400 | #if DEBUG | 1398 | #if DEBUG |
1401 | fprintf(stderr,"checkPerm: '%s' ? '%s'\n", p0, request); | 1399 | fprintf(stderr,"checkPerm: '%s' ? '%s'\n", p0, request); |
1402 | #endif | 1400 | #endif |
1403 | { | ||
1404 | size_t l = strlen(p0); | ||
1405 | |||
1406 | if(strncmp(p0, path, l) == 0 && | ||
1407 | (l == 1 || path[l] == '/' || path[l] == 0)) { | ||
1408 | char *u; | ||
1409 | /* path match found. Check request */ | ||
1410 | /* for check next /path:user:password */ | ||
1411 | prev = p0; | ||
1412 | u = strchr(request, ':'); | ||
1413 | if(u == NULL) { | ||
1414 | /* bad request, ':' required */ | ||
1415 | break; | ||
1416 | } | ||
1417 | |||
1418 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | ||
1419 | { | 1401 | { |
1420 | char *cipher; | 1402 | size_t l = strlen(p0); |
1421 | char *pp; | 1403 | |
1404 | if (strncmp(p0, path, l) == 0 && | ||
1405 | (l == 1 || path[l] == '/' || path[l] == 0)) { | ||
1406 | char *u; | ||
1407 | /* path match found. Check request */ | ||
1408 | /* for check next /path:user:password */ | ||
1409 | prev = p0; | ||
1410 | u = strchr(request, ':'); | ||
1411 | if (u == NULL) { | ||
1412 | /* bad request, ':' required */ | ||
1413 | break; | ||
1414 | } | ||
1422 | 1415 | ||
1423 | if(strncmp(p, request, u-request) != 0) { | 1416 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 |
1424 | /* user uncompared */ | 1417 | { |
1425 | continue; | 1418 | char *cipher; |
1426 | } | 1419 | char *pp; |
1427 | pp = strchr(p, ':'); | 1420 | |
1428 | if(pp && pp[1] == '$' && pp[2] == '1' && | 1421 | if (strncmp(p, request, u-request) != 0) { |
1429 | pp[3] == '$' && pp[4]) { | 1422 | /* user uncompared */ |
1430 | pp++; | 1423 | continue; |
1431 | cipher = pw_encrypt(u+1, pp); | 1424 | } |
1432 | if (strcmp(cipher, pp) == 0) | 1425 | pp = strchr(p, ':'); |
1433 | goto set_remoteuser_var; /* Ok */ | 1426 | if (pp && pp[1] == '$' && pp[2] == '1' && |
1434 | /* unauthorized */ | 1427 | pp[3] == '$' && pp[4]) { |
1435 | continue; | 1428 | pp++; |
1436 | } | 1429 | cipher = pw_encrypt(u+1, pp); |
1437 | } | 1430 | if (strcmp(cipher, pp) == 0) |
1431 | goto set_remoteuser_var; /* Ok */ | ||
1432 | /* unauthorized */ | ||
1433 | continue; | ||
1434 | } | ||
1435 | } | ||
1438 | #endif | 1436 | #endif |
1439 | if (strcmp(p, request) == 0) { | 1437 | if (strcmp(p, request) == 0) { |
1440 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | 1438 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 |
1441 | set_remoteuser_var: | 1439 | set_remoteuser_var: |
1442 | #endif | 1440 | #endif |
1443 | config->remoteuser = strdup(request); | 1441 | config->remoteuser = strdup(request); |
1444 | if(config->remoteuser) | 1442 | if (config->remoteuser) |
1445 | config->remoteuser[(u - request)] = 0; | 1443 | config->remoteuser[(u - request)] = 0; |
1446 | return 1; /* Ok */ | 1444 | return 1; /* Ok */ |
1445 | } | ||
1446 | /* unauthorized */ | ||
1447 | } | ||
1447 | } | 1448 | } |
1448 | /* unauthorized */ | 1449 | } /* for */ |
1449 | } | ||
1450 | } | ||
1451 | } /* for */ | ||
1452 | 1450 | ||
1453 | return prev == NULL; | 1451 | return prev == NULL; |
1454 | } | 1452 | } |
1455 | 1453 | ||
1456 | #endif /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */ | 1454 | #endif /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */ |
@@ -1463,11 +1461,10 @@ set_remoteuser_var: | |||
1463 | * | 1461 | * |
1464 | ****************************************************************************/ | 1462 | ****************************************************************************/ |
1465 | 1463 | ||
1466 | static void | 1464 | static void handle_sigalrm(int sig) |
1467 | handle_sigalrm( int sig ) | ||
1468 | { | 1465 | { |
1469 | sendHeaders(HTTP_REQUEST_TIMEOUT); | 1466 | sendHeaders(HTTP_REQUEST_TIMEOUT); |
1470 | config->alarm_signaled = sig; | 1467 | config->alarm_signaled = sig; |
1471 | } | 1468 | } |
1472 | 1469 | ||
1473 | /**************************************************************************** | 1470 | /**************************************************************************** |
@@ -1479,283 +1476,283 @@ handle_sigalrm( int sig ) | |||
1479 | ****************************************************************************/ | 1476 | ****************************************************************************/ |
1480 | static void handleIncoming(void) | 1477 | static void handleIncoming(void) |
1481 | { | 1478 | { |
1482 | char *buf = config->buf; | 1479 | char *buf = config->buf; |
1483 | char *url; | 1480 | char *url; |
1484 | char *purl; | 1481 | char *purl; |
1485 | int blank = -1; | 1482 | int blank = -1; |
1486 | char *test; | 1483 | char *test; |
1487 | struct stat sb; | 1484 | struct stat sb; |
1488 | int ip_allowed; | 1485 | int ip_allowed; |
1489 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1486 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1490 | const char *prequest = request_GET; | 1487 | const char *prequest = request_GET; |
1491 | long length=0; | 1488 | long length=0; |
1492 | char *cookie = 0; | 1489 | char *cookie = 0; |
1493 | char *content_type = 0; | 1490 | char *content_type = 0; |
1494 | #endif | 1491 | #endif |
1495 | fd_set s_fd; | 1492 | fd_set s_fd; |
1496 | struct timeval tv; | 1493 | struct timeval tv; |
1497 | int retval; | 1494 | int retval; |
1498 | struct sigaction sa; | 1495 | struct sigaction sa; |
1499 | 1496 | ||
1500 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1497 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1501 | int credentials = -1; /* if not requred this is Ok */ | 1498 | int credentials = -1; /* if not requred this is Ok */ |
1502 | #endif | 1499 | #endif |
1503 | 1500 | ||
1504 | sa.sa_handler = handle_sigalrm; | 1501 | sa.sa_handler = handle_sigalrm; |
1505 | sigemptyset(&sa.sa_mask); | 1502 | sigemptyset(&sa.sa_mask); |
1506 | sa.sa_flags = 0; /* no SA_RESTART */ | 1503 | sa.sa_flags = 0; /* no SA_RESTART */ |
1507 | sigaction(SIGALRM, &sa, NULL); | 1504 | sigaction(SIGALRM, &sa, NULL); |
1508 | 1505 | ||
1509 | do { | 1506 | do { |
1510 | int count; | 1507 | int count; |
1511 | 1508 | ||
1512 | (void) alarm( TIMEOUT ); | 1509 | (void) alarm(TIMEOUT); |
1513 | if (getLine() <= 0) | 1510 | if (getLine() <= 0) |
1514 | break; /* closed */ | 1511 | break; /* closed */ |
1515 | 1512 | ||
1516 | purl = strpbrk(buf, " \t"); | 1513 | purl = strpbrk(buf, " \t"); |
1517 | if(purl == NULL) { | 1514 | if (purl == NULL) { |
1518 | BAD_REQUEST: | 1515 | BAD_REQUEST: |
1519 | sendHeaders(HTTP_BAD_REQUEST); | 1516 | sendHeaders(HTTP_BAD_REQUEST); |
1520 | break; | 1517 | break; |
1521 | } | 1518 | } |
1522 | *purl = 0; | 1519 | *purl = 0; |
1523 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1520 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1524 | if(strcasecmp(buf, prequest) != 0) { | 1521 | if (strcasecmp(buf, prequest) != 0) { |
1525 | prequest = "POST"; | 1522 | prequest = "POST"; |
1526 | if(strcasecmp(buf, prequest) != 0) { | 1523 | if (strcasecmp(buf, prequest) != 0) { |
1527 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1524 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1528 | break; | 1525 | break; |
1529 | } | 1526 | } |
1530 | } | 1527 | } |
1531 | #else | 1528 | #else |
1532 | if(strcasecmp(buf, request_GET) != 0) { | 1529 | if (strcasecmp(buf, request_GET) != 0) { |
1533 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1530 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1534 | break; | 1531 | break; |
1535 | } | 1532 | } |
1536 | #endif | 1533 | #endif |
1537 | *purl = ' '; | 1534 | *purl = ' '; |
1538 | count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank); | 1535 | count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank); |
1539 | 1536 | ||
1540 | if (count < 1 || buf[0] != '/') { | 1537 | if (count < 1 || buf[0] != '/') { |
1541 | /* Garbled request/URL */ | 1538 | /* Garbled request/URL */ |
1542 | goto BAD_REQUEST; | ||
1543 | } | ||
1544 | url = alloca(strlen(buf) + 12); /* + sizeof("/index.html\0") */ | ||
1545 | if(url == NULL) { | ||
1546 | sendHeaders(HTTP_INTERNAL_SERVER_ERROR); | ||
1547 | break; | ||
1548 | } | ||
1549 | strcpy(url, buf); | ||
1550 | /* extract url args if present */ | ||
1551 | test = strchr(url, '?'); | ||
1552 | if (test) { | ||
1553 | *test++ = 0; | ||
1554 | config->query = test; | ||
1555 | } | ||
1556 | |||
1557 | test = decodeString(url, 0); | ||
1558 | if(test == NULL) | ||
1559 | goto BAD_REQUEST; | ||
1560 | if(test == (buf+1)) { | ||
1561 | sendHeaders(HTTP_NOT_FOUND); | ||
1562 | break; | ||
1563 | } | ||
1564 | /* algorithm stolen from libbb bb_simplify_path(), | ||
1565 | but don`t strdup and reducing trailing slash and protect out root */ | ||
1566 | purl = test = url; | ||
1567 | |||
1568 | do { | ||
1569 | if (*purl == '/') { | ||
1570 | if (*test == '/') { /* skip duplicate (or initial) slash */ | ||
1571 | continue; | ||
1572 | } else if (*test == '.') { | ||
1573 | if (test[1] == '/' || test[1] == 0) { /* skip extra '.' */ | ||
1574 | continue; | ||
1575 | } else if ((test[1] == '.') && (test[2] == '/' || test[2] == 0)) { | ||
1576 | ++test; | ||
1577 | if (purl == url) { | ||
1578 | /* protect out root */ | ||
1579 | goto BAD_REQUEST; | 1539 | goto BAD_REQUEST; |
1580 | } | ||
1581 | while (*--purl != '/'); /* omit previous dir */ | ||
1582 | continue; | ||
1583 | } | 1540 | } |
1584 | } | 1541 | url = alloca(strlen(buf) + 12); /* + sizeof("/index.html\0") */ |
1585 | } | 1542 | if (url == NULL) { |
1586 | *++purl = *test; | 1543 | sendHeaders(HTTP_INTERNAL_SERVER_ERROR); |
1587 | } while (*++test); | 1544 | break; |
1588 | 1545 | } | |
1589 | *++purl = 0; /* so keep last character */ | 1546 | strcpy(url, buf); |
1590 | test = purl; /* end ptr */ | 1547 | /* extract url args if present */ |
1591 | 1548 | test = strchr(url, '?'); | |
1592 | /* If URL is directory, adding '/' */ | 1549 | if (test) { |
1593 | if(test[-1] != '/') { | 1550 | *test++ = 0; |
1594 | if ( is_directory(url + 1, 1, &sb) ) { | 1551 | config->query = test; |
1595 | config->httpd_found.found_moved_temporarily = url; | 1552 | } |
1596 | } | 1553 | |
1597 | } | 1554 | test = decodeString(url, 0); |
1555 | if (test == NULL) | ||
1556 | goto BAD_REQUEST; | ||
1557 | if (test == (buf+1)) { | ||
1558 | sendHeaders(HTTP_NOT_FOUND); | ||
1559 | break; | ||
1560 | } | ||
1561 | /* algorithm stolen from libbb bb_simplify_path(), | ||
1562 | but don`t strdup and reducing trailing slash and protect out root */ | ||
1563 | purl = test = url; | ||
1564 | |||
1565 | do { | ||
1566 | if (*purl == '/') { | ||
1567 | if (*test == '/') { /* skip duplicate (or initial) slash */ | ||
1568 | continue; | ||
1569 | } else if (*test == '.') { | ||
1570 | if (test[1] == '/' || test[1] == 0) { /* skip extra '.' */ | ||
1571 | continue; | ||
1572 | } else if ((test[1] == '.') && (test[2] == '/' || test[2] == 0)) { | ||
1573 | ++test; | ||
1574 | if (purl == url) { | ||
1575 | /* protect out root */ | ||
1576 | goto BAD_REQUEST; | ||
1577 | } | ||
1578 | while (*--purl != '/'); /* omit previous dir */ | ||
1579 | continue; | ||
1580 | } | ||
1581 | } | ||
1582 | } | ||
1583 | *++purl = *test; | ||
1584 | } while (*++test); | ||
1585 | |||
1586 | *++purl = 0; /* so keep last character */ | ||
1587 | test = purl; /* end ptr */ | ||
1588 | |||
1589 | /* If URL is directory, adding '/' */ | ||
1590 | if (test[-1] != '/') { | ||
1591 | if (is_directory(url + 1, 1, &sb)) { | ||
1592 | config->httpd_found.found_moved_temporarily = url; | ||
1593 | } | ||
1594 | } | ||
1598 | #if DEBUG | 1595 | #if DEBUG |
1599 | fprintf(stderr, "url='%s', args=%s\n", url, config->query); | 1596 | fprintf(stderr, "url='%s', args=%s\n", url, config->query); |
1600 | #endif | 1597 | #endif |
1601 | 1598 | ||
1602 | test = url; | 1599 | test = url; |
1603 | ip_allowed = checkPermIP(); | ||
1604 | while(ip_allowed && (test = strchr( test + 1, '/' )) != NULL) { | ||
1605 | /* have path1/path2 */ | ||
1606 | *test = '\0'; | ||
1607 | if( is_directory(url + 1, 1, &sb) ) { | ||
1608 | /* may be having subdir config */ | ||
1609 | parse_conf(url + 1, SUBDIR_PARSE); | ||
1610 | ip_allowed = checkPermIP(); | 1600 | ip_allowed = checkPermIP(); |
1611 | } | 1601 | while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) { |
1612 | *test = '/'; | 1602 | /* have path1/path2 */ |
1613 | } | 1603 | *test = '\0'; |
1614 | if(blank >= 0) { | 1604 | if (is_directory(url + 1, 1, &sb)) { |
1615 | // read until blank line for HTTP version specified, else parse immediate | 1605 | /* may be having subdir config */ |
1616 | while(1) { | 1606 | parse_conf(url + 1, SUBDIR_PARSE); |
1617 | alarm(TIMEOUT); | 1607 | ip_allowed = checkPermIP(); |
1618 | count = getLine(); | 1608 | } |
1619 | if(count <= 0) | 1609 | *test = '/'; |
1620 | break; | 1610 | } |
1611 | if (blank >= 0) { | ||
1612 | // read until blank line for HTTP version specified, else parse immediate | ||
1613 | while (1) { | ||
1614 | alarm(TIMEOUT); | ||
1615 | count = getLine(); | ||
1616 | if (count <= 0) | ||
1617 | break; | ||
1621 | 1618 | ||
1622 | #if DEBUG | 1619 | #if DEBUG |
1623 | fprintf(stderr, "Header: '%s'\n", buf); | 1620 | fprintf(stderr, "Header: '%s'\n", buf); |
1624 | #endif | 1621 | #endif |
1625 | 1622 | ||
1626 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1623 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1627 | /* try and do our best to parse more lines */ | 1624 | /* try and do our best to parse more lines */ |
1628 | if ((strncasecmp(buf, Content_length, 15) == 0)) { | 1625 | if ((strncasecmp(buf, Content_length, 15) == 0)) { |
1629 | if(prequest != request_GET) | 1626 | if (prequest != request_GET) |
1630 | length = strtol(buf + 15, 0, 0); // extra read only for POST | 1627 | length = strtol(buf + 15, 0, 0); // extra read only for POST |
1631 | } else if ((strncasecmp(buf, "Cookie:", 7) == 0)) { | 1628 | } else if ((strncasecmp(buf, "Cookie:", 7) == 0)) { |
1632 | for(test = buf + 7; isspace(*test); test++) | 1629 | for (test = buf + 7; isspace(*test); test++) |
1633 | ; | 1630 | ; |
1634 | cookie = strdup(test); | 1631 | cookie = strdup(test); |
1635 | } else if ((strncasecmp(buf, "Content-Type:", 13) == 0)) { | 1632 | } else if ((strncasecmp(buf, "Content-Type:", 13) == 0)) { |
1636 | for(test = buf + 13; isspace(*test); test++) | 1633 | for (test = buf + 13; isspace(*test); test++) |
1637 | ; | 1634 | ; |
1638 | content_type = strdup(test); | 1635 | content_type = strdup(test); |
1639 | } else if ((strncasecmp(buf, "Referer:", 8) == 0)) { | 1636 | } else if ((strncasecmp(buf, "Referer:", 8) == 0)) { |
1640 | for(test = buf + 8; isspace(*test); test++) | 1637 | for (test = buf + 8; isspace(*test); test++) |
1641 | ; | 1638 | ; |
1642 | config->referer = strdup(test); | 1639 | config->referer = strdup(test); |
1643 | } | 1640 | } |
1644 | #endif | 1641 | #endif |
1645 | 1642 | ||
1646 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1643 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1647 | if (strncasecmp(buf, "Authorization:", 14) == 0) { | 1644 | if (strncasecmp(buf, "Authorization:", 14) == 0) { |
1648 | /* We only allow Basic credentials. | 1645 | /* We only allow Basic credentials. |
1649 | * It shows up as "Authorization: Basic <userid:password>" where | 1646 | * It shows up as "Authorization: Basic <userid:password>" where |
1650 | * the userid:password is base64 encoded. | 1647 | * the userid:password is base64 encoded. |
1651 | */ | 1648 | */ |
1652 | for(test = buf + 14; isspace(*test); test++) | 1649 | for (test = buf + 14; isspace(*test); test++) |
1653 | ; | 1650 | ; |
1654 | if (strncasecmp(test, "Basic", 5) != 0) | 1651 | if (strncasecmp(test, "Basic", 5) != 0) |
1655 | continue; | 1652 | continue; |
1656 | 1653 | ||
1657 | test += 5; /* decodeBase64() skiping space self */ | 1654 | test += 5; /* decodeBase64() skiping space self */ |
1658 | decodeBase64(test); | 1655 | decodeBase64(test); |
1659 | credentials = checkPerm(url, test); | 1656 | credentials = checkPerm(url, test); |
1660 | } | 1657 | } |
1661 | #endif /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */ | 1658 | #endif /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */ |
1662 | 1659 | ||
1663 | } /* while extra header reading */ | 1660 | } /* while extra header reading */ |
1664 | } | 1661 | } |
1665 | (void) alarm( 0 ); | 1662 | (void) alarm(0); |
1666 | if(config->alarm_signaled) | 1663 | if (config->alarm_signaled) |
1667 | break; | 1664 | break; |
1668 | 1665 | ||
1669 | if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { | 1666 | if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) { |
1670 | /* protect listing [/path]/httpd_conf or IP deny */ | 1667 | /* protect listing [/path]/httpd_conf or IP deny */ |
1671 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1668 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1672 | FORBIDDEN: /* protect listing /cgi-bin */ | 1669 | FORBIDDEN: /* protect listing /cgi-bin */ |
1673 | #endif | 1670 | #endif |
1674 | sendHeaders(HTTP_FORBIDDEN); | 1671 | sendHeaders(HTTP_FORBIDDEN); |
1675 | break; | 1672 | break; |
1676 | } | 1673 | } |
1677 | 1674 | ||
1678 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1675 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1679 | if (credentials <= 0 && checkPerm(url, ":") == 0) { | 1676 | if (credentials <= 0 && checkPerm(url, ":") == 0) { |
1680 | sendHeaders(HTTP_UNAUTHORIZED); | 1677 | sendHeaders(HTTP_UNAUTHORIZED); |
1681 | break; | 1678 | break; |
1682 | } | 1679 | } |
1683 | #endif | 1680 | #endif |
1684 | 1681 | ||
1685 | if(config->httpd_found.found_moved_temporarily) { | 1682 | if (config->httpd_found.found_moved_temporarily) { |
1686 | sendHeaders(HTTP_MOVED_TEMPORARILY); | 1683 | sendHeaders(HTTP_MOVED_TEMPORARILY); |
1687 | #if DEBUG | 1684 | #if DEBUG |
1688 | /* clear unforked memory flag */ | 1685 | /* clear unforked memory flag */ |
1689 | config->httpd_found.found_moved_temporarily = NULL; | 1686 | config->httpd_found.found_moved_temporarily = NULL; |
1690 | #endif | 1687 | #endif |
1691 | break; | 1688 | break; |
1692 | } | 1689 | } |
1693 | 1690 | ||
1694 | test = url + 1; /* skip first '/' */ | 1691 | test = url + 1; /* skip first '/' */ |
1695 | 1692 | ||
1696 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1693 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1697 | /* if strange Content-Length */ | 1694 | /* if strange Content-Length */ |
1698 | if (length < 0) | 1695 | if (length < 0) |
1699 | break; | 1696 | break; |
1700 | 1697 | ||
1701 | if (strncmp(test, "cgi-bin", 7) == 0) { | 1698 | if (strncmp(test, "cgi-bin", 7) == 0) { |
1702 | if(test[7] == '/' && test[8] == 0) | 1699 | if (test[7] == '/' && test[8] == 0) |
1703 | goto FORBIDDEN; // protect listing cgi-bin/ | 1700 | goto FORBIDDEN; // protect listing cgi-bin/ |
1704 | sendCgi(url, prequest, length, cookie, content_type); | 1701 | sendCgi(url, prequest, length, cookie, content_type); |
1705 | } else { | 1702 | } else { |
1706 | if (prequest != request_GET) | 1703 | if (prequest != request_GET) |
1707 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1704 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1708 | else { | 1705 | else { |
1709 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ | 1706 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ |
1710 | if(purl[-1] == '/') | 1707 | if (purl[-1] == '/') |
1711 | strcpy(purl, "index.html"); | 1708 | strcpy(purl, "index.html"); |
1712 | if ( stat(test, &sb ) == 0 ) { | 1709 | if (stat(test, &sb) == 0) { |
1713 | config->ContentLength = sb.st_size; | 1710 | config->ContentLength = sb.st_size; |
1714 | config->last_mod = sb.st_mtime; | 1711 | config->last_mod = sb.st_mtime; |
1715 | } | 1712 | } |
1716 | sendFile(test); | 1713 | sendFile(test); |
1717 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1714 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1718 | /* unset if non inetd looped */ | 1715 | /* unset if non inetd looped */ |
1719 | config->ContentLength = -1; | 1716 | config->ContentLength = -1; |
1720 | #endif | 1717 | #endif |
1721 | 1718 | ||
1722 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1719 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1723 | } | 1720 | } |
1724 | } | 1721 | } |
1725 | #endif | 1722 | #endif |
1726 | 1723 | ||
1727 | } while (0); | 1724 | } while (0); |
1728 | 1725 | ||
1729 | 1726 | ||
1730 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1727 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1731 | /* from inetd don`t looping: freeing, closing automatic from exit always */ | 1728 | /* from inetd don`t looping: freeing, closing automatic from exit always */ |
1732 | # if DEBUG | 1729 | # if DEBUG |
1733 | fprintf(stderr, "closing socket\n"); | 1730 | fprintf(stderr, "closing socket\n"); |
1734 | # endif | 1731 | # endif |
1735 | # ifdef CONFIG_FEATURE_HTTPD_CGI | 1732 | # ifdef CONFIG_FEATURE_HTTPD_CGI |
1736 | free(cookie); | 1733 | free(cookie); |
1737 | free(content_type); | 1734 | free(content_type); |
1738 | free(config->referer); | 1735 | free(config->referer); |
1739 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1736 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1740 | free(config->remoteuser); | 1737 | free(config->remoteuser); |
1741 | #endif | 1738 | #endif |
1742 | # endif | 1739 | # endif |
1743 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ | 1740 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ |
1744 | shutdown(a_c_w, SHUT_WR); | 1741 | shutdown(a_c_w, SHUT_WR); |
1745 | 1742 | ||
1746 | /* Properly wait for remote to closed */ | 1743 | /* Properly wait for remote to closed */ |
1747 | FD_ZERO (&s_fd) ; | 1744 | FD_ZERO (&s_fd) ; |
1748 | FD_SET (a_c_r, &s_fd) ; | 1745 | FD_SET (a_c_r, &s_fd) ; |
1749 | 1746 | ||
1750 | do { | 1747 | do { |
1751 | tv.tv_sec = 2 ; | 1748 | tv.tv_sec = 2 ; |
1752 | tv.tv_usec = 0 ; | 1749 | tv.tv_usec = 0 ; |
1753 | retval = select (a_c_r + 1, &s_fd, NULL, NULL, &tv); | 1750 | retval = select (a_c_r + 1, &s_fd, NULL, NULL, &tv); |
1754 | } while (retval > 0 && (read (a_c_r, buf, sizeof (config->buf)) > 0)); | 1751 | } while (retval > 0 && (read (a_c_r, buf, sizeof (config->buf)) > 0)); |
1755 | 1752 | ||
1756 | shutdown(a_c_r, SHUT_RD); | 1753 | shutdown(a_c_r, SHUT_RD); |
1757 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1754 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1758 | close(config->accepted_socket); | 1755 | close(config->accepted_socket); |
1759 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ | 1756 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ |
1760 | } | 1757 | } |
1761 | 1758 | ||
@@ -1777,88 +1774,88 @@ FORBIDDEN: /* protect listing /cgi-bin */ | |||
1777 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1774 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1778 | static int miniHttpd(int server) | 1775 | static int miniHttpd(int server) |
1779 | { | 1776 | { |
1780 | fd_set readfd, portfd; | 1777 | fd_set readfd, portfd; |
1781 | 1778 | ||
1782 | FD_ZERO(&portfd); | 1779 | FD_ZERO(&portfd); |
1783 | FD_SET(server, &portfd); | 1780 | FD_SET(server, &portfd); |
1784 | 1781 | ||
1785 | /* copy the ports we are watching to the readfd set */ | 1782 | /* copy the ports we are watching to the readfd set */ |
1786 | while (1) { | 1783 | while (1) { |
1787 | readfd = portfd; | 1784 | readfd = portfd; |
1788 | 1785 | ||
1789 | /* Now wait INDEFINITELY on the set of sockets! */ | 1786 | /* Now wait INDEFINITELY on the set of sockets! */ |
1790 | if (select(server + 1, &readfd, 0, 0, 0) > 0) { | 1787 | if (select(server + 1, &readfd, 0, 0, 0) > 0) { |
1791 | if (FD_ISSET(server, &readfd)) { | 1788 | if (FD_ISSET(server, &readfd)) { |
1792 | int on; | 1789 | int on; |
1793 | struct sockaddr_in fromAddr; | 1790 | struct sockaddr_in fromAddr; |
1794 | 1791 | ||
1795 | socklen_t fromAddrLen = sizeof(fromAddr); | 1792 | socklen_t fromAddrLen = sizeof(fromAddr); |
1796 | int s = accept(server, | 1793 | int s = accept(server, |
1797 | (struct sockaddr *)&fromAddr, &fromAddrLen); | 1794 | (struct sockaddr *)&fromAddr, &fromAddrLen); |
1798 | 1795 | ||
1799 | if (s < 0) { | 1796 | if (s < 0) { |
1800 | continue; | 1797 | continue; |
1801 | } | 1798 | } |
1802 | config->accepted_socket = s; | 1799 | config->accepted_socket = s; |
1803 | config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr); | 1800 | config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr); |
1804 | #if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG | 1801 | #if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG |
1805 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", | 1802 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", |
1806 | (unsigned char)(config->rmt_ip >> 24), | 1803 | (unsigned char)(config->rmt_ip >> 24), |
1807 | (unsigned char)(config->rmt_ip >> 16), | 1804 | (unsigned char)(config->rmt_ip >> 16), |
1808 | (unsigned char)(config->rmt_ip >> 8), | 1805 | (unsigned char)(config->rmt_ip >> 8), |
1809 | config->rmt_ip & 0xff); | 1806 | config->rmt_ip & 0xff); |
1810 | config->port = ntohs(fromAddr.sin_port); | 1807 | config->port = ntohs(fromAddr.sin_port); |
1811 | #if DEBUG | 1808 | #if DEBUG |
1812 | bb_error_msg("connection from IP=%s, port %u", | 1809 | bb_error_msg("connection from IP=%s, port %u", |
1813 | config->rmt_ip_str, config->port); | 1810 | config->rmt_ip_str, config->port); |
1814 | #endif | 1811 | #endif |
1815 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ | 1812 | #endif /* CONFIG_FEATURE_HTTPD_CGI */ |
1816 | 1813 | ||
1817 | /* set the KEEPALIVE option to cull dead connections */ | 1814 | /* set the KEEPALIVE option to cull dead connections */ |
1818 | on = 1; | 1815 | on = 1; |
1819 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof (on)); | 1816 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof (on)); |
1820 | 1817 | ||
1821 | #if !DEBUG | 1818 | #if !DEBUG |
1822 | if (fork() == 0) | 1819 | if (fork() == 0) |
1823 | #endif | 1820 | #endif |
1824 | { | 1821 | { |
1825 | /* This is the spawned thread */ | 1822 | /* This is the spawned thread */ |
1826 | #ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP | 1823 | #ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP |
1827 | /* protect reload config, may be confuse checking */ | 1824 | /* protect reload config, may be confuse checking */ |
1828 | signal(SIGHUP, SIG_IGN); | 1825 | signal(SIGHUP, SIG_IGN); |
1829 | #endif | 1826 | #endif |
1830 | handleIncoming(); | 1827 | handleIncoming(); |
1831 | #if !DEBUG | 1828 | #if !DEBUG |
1832 | exit(0); | 1829 | exit(0); |
1833 | #endif | 1830 | #endif |
1834 | } | 1831 | } |
1835 | close(s); | 1832 | close(s); |
1836 | } | 1833 | } |
1837 | } | 1834 | } |
1838 | } // while (1) | 1835 | } // while (1) |
1839 | return 0; | 1836 | return 0; |
1840 | } | 1837 | } |
1841 | 1838 | ||
1842 | #else | 1839 | #else |
1843 | /* from inetd */ | 1840 | /* from inetd */ |
1844 | 1841 | ||
1845 | static int miniHttpd(void) | 1842 | static int miniHttpd(void) |
1846 | { | 1843 | { |
1847 | struct sockaddr_in fromAddrLen; | 1844 | struct sockaddr_in fromAddrLen; |
1848 | socklen_t sinlen = sizeof (struct sockaddr_in); | 1845 | socklen_t sinlen = sizeof (struct sockaddr_in); |
1849 | 1846 | ||
1850 | getpeername (0, (struct sockaddr *)&fromAddrLen, &sinlen); | 1847 | getpeername (0, (struct sockaddr *)&fromAddrLen, &sinlen); |
1851 | config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr); | 1848 | config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr); |
1852 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1849 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1853 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", | 1850 | sprintf(config->rmt_ip_str, "%u.%u.%u.%u", |
1854 | (unsigned char)(config->rmt_ip >> 24), | 1851 | (unsigned char)(config->rmt_ip >> 24), |
1855 | (unsigned char)(config->rmt_ip >> 16), | 1852 | (unsigned char)(config->rmt_ip >> 16), |
1856 | (unsigned char)(config->rmt_ip >> 8), | 1853 | (unsigned char)(config->rmt_ip >> 8), |
1857 | config->rmt_ip & 0xff); | 1854 | config->rmt_ip & 0xff); |
1858 | #endif | 1855 | #endif |
1859 | config->port = ntohs(fromAddrLen.sin_port); | 1856 | config->port = ntohs(fromAddrLen.sin_port); |
1860 | handleIncoming(); | 1857 | handleIncoming(); |
1861 | return 0; | 1858 | return 0; |
1862 | } | 1859 | } |
1863 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ | 1860 | #endif /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */ |
1864 | 1861 | ||
@@ -1868,8 +1865,7 @@ static void sighup_handler(int sig) | |||
1868 | /* set and reset */ | 1865 | /* set and reset */ |
1869 | struct sigaction sa; | 1866 | struct sigaction sa; |
1870 | 1867 | ||
1871 | parse_conf(default_path_httpd_conf, | 1868 | parse_conf(default_path_httpd_conf, sig == SIGHUP ? SIGNALED_PARSE : FIRST_PARSE); |
1872 | sig == SIGHUP ? SIGNALED_PARSE : FIRST_PARSE); | ||
1873 | sa.sa_handler = sighup_handler; | 1869 | sa.sa_handler = sighup_handler; |
1874 | sigemptyset(&sa.sa_mask); | 1870 | sigemptyset(&sa.sa_mask); |
1875 | sa.sa_flags = SA_RESTART; | 1871 | sa.sa_flags = SA_RESTART; |
@@ -1900,124 +1896,124 @@ static const char httpd_opts[]="c:d:h:" | |||
1900 | #define OPT_HOME_HTTPD (1<<h_opt_home_httpd) | 1896 | #define OPT_HOME_HTTPD (1<<h_opt_home_httpd) |
1901 | 1897 | ||
1902 | #define OPT_ENCODE_URL USE_FEATURE_HTTPD_ENCODE_URL_STR((1<<e_opt_encode_url)) \ | 1898 | #define OPT_ENCODE_URL USE_FEATURE_HTTPD_ENCODE_URL_STR((1<<e_opt_encode_url)) \ |
1903 | SKIP_FEATURE_HTTPD_ENCODE_URL_STR(0) | 1899 | SKIP_FEATURE_HTTPD_ENCODE_URL_STR(0) |
1904 | 1900 | ||
1905 | #define OPT_REALM USE_FEATURE_HTTPD_BASIC_AUTH((1<<r_opt_realm)) \ | 1901 | #define OPT_REALM USE_FEATURE_HTTPD_BASIC_AUTH((1<<r_opt_realm)) \ |
1906 | SKIP_FEATURE_HTTPD_BASIC_AUTH(0) | 1902 | SKIP_FEATURE_HTTPD_BASIC_AUTH(0) |
1907 | 1903 | ||
1908 | #define OPT_MD5 USE_FEATURE_HTTPD_AUTH_MD5((1<<m_opt_md5)) \ | 1904 | #define OPT_MD5 USE_FEATURE_HTTPD_AUTH_MD5((1<<m_opt_md5)) \ |
1909 | SKIP_FEATURE_HTTPD_AUTH_MD5(0) | 1905 | SKIP_FEATURE_HTTPD_AUTH_MD5(0) |
1910 | 1906 | ||
1911 | #define OPT_SETUID USE_FEATURE_HTTPD_SETUID((1<<u_opt_setuid)) \ | 1907 | #define OPT_SETUID USE_FEATURE_HTTPD_SETUID((1<<u_opt_setuid)) \ |
1912 | SKIP_FEATURE_HTTPD_SETUID(0) | 1908 | SKIP_FEATURE_HTTPD_SETUID(0) |
1913 | 1909 | ||
1914 | #define OPT_PORT USE_FEATURE_HTTPD_WITHOUT_INETD((1<<p_opt_port)) \ | 1910 | #define OPT_PORT USE_FEATURE_HTTPD_WITHOUT_INETD((1<<p_opt_port)) \ |
1915 | SKIP_FEATURE_HTTPD_WITHOUT_INETD(0) | 1911 | SKIP_FEATURE_HTTPD_WITHOUT_INETD(0) |
1916 | 1912 | ||
1917 | 1913 | ||
1918 | int httpd_main(int argc, char *argv[]) | 1914 | int httpd_main(int argc, char *argv[]) |
1919 | { | 1915 | { |
1920 | unsigned long opt; | 1916 | unsigned long opt; |
1921 | const char *home_httpd = home; | 1917 | const char *home_httpd = home; |
1922 | char *url_for_decode; | 1918 | char *url_for_decode; |
1923 | USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) | 1919 | USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;) |
1924 | USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_port;) | 1920 | USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_port;) |
1925 | USE_FEATURE_HTTPD_WITHOUT_INETD(int server;) | 1921 | USE_FEATURE_HTTPD_WITHOUT_INETD(int server;) |
1926 | 1922 | ||
1927 | USE_FEATURE_HTTPD_SETUID(const char *s_uid;) | 1923 | USE_FEATURE_HTTPD_SETUID(const char *s_uid;) |
1928 | USE_FEATURE_HTTPD_SETUID(long uid = -1;) | 1924 | USE_FEATURE_HTTPD_SETUID(long uid = -1;) |
1929 | 1925 | ||
1930 | USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;) | 1926 | USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;) |
1931 | 1927 | ||
1932 | config = xzalloc(sizeof(*config)); | 1928 | config = xzalloc(sizeof(*config)); |
1933 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH | 1929 | #ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH |
1934 | config->realm = "Web Server Authentication"; | 1930 | config->realm = "Web Server Authentication"; |
1935 | #endif | 1931 | #endif |
1936 | 1932 | ||
1937 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1933 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1938 | config->port = 80; | 1934 | config->port = 80; |
1939 | #endif | 1935 | #endif |
1940 | 1936 | ||
1941 | config->ContentLength = -1; | 1937 | config->ContentLength = -1; |
1942 | 1938 | ||
1943 | opt = bb_getopt_ulflags(argc, argv, httpd_opts, | 1939 | opt = bb_getopt_ulflags(argc, argv, httpd_opts, |
1944 | &(config->configFile), &url_for_decode, &home_httpd | 1940 | &(config->configFile), &url_for_decode, &home_httpd |
1945 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | 1941 | USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
1946 | USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) | 1942 | USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) |
1947 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | 1943 | USE_FEATURE_HTTPD_AUTH_MD5(, &pass) |
1948 | USE_FEATURE_HTTPD_SETUID(, &s_uid) | 1944 | USE_FEATURE_HTTPD_SETUID(, &s_uid) |
1949 | USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_port) | 1945 | USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_port) |
1950 | ); | 1946 | ); |
1951 | 1947 | ||
1952 | if(opt & OPT_DECODE_URL) { | 1948 | if (opt & OPT_DECODE_URL) { |
1953 | printf("%s", decodeString(url_for_decode, 1)); | 1949 | printf("%s", decodeString(url_for_decode, 1)); |
1954 | return 0; | 1950 | return 0; |
1955 | } | 1951 | } |
1956 | #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR | 1952 | #ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR |
1957 | if(opt & OPT_ENCODE_URL) { | 1953 | if (opt & OPT_ENCODE_URL) { |
1958 | printf("%s", encodeString(url_for_encode)); | 1954 | printf("%s", encodeString(url_for_encode)); |
1959 | return 0; | 1955 | return 0; |
1960 | } | 1956 | } |
1961 | #endif | 1957 | #endif |
1962 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 | 1958 | #ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5 |
1963 | if(opt & OPT_MD5) { | 1959 | if (opt & OPT_MD5) { |
1964 | printf("%s\n", pw_encrypt(pass, "$1$")); | 1960 | printf("%s\n", pw_encrypt(pass, "$1$")); |
1965 | return 0; | 1961 | return 0; |
1966 | } | 1962 | } |
1967 | #endif | 1963 | #endif |
1968 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1964 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1969 | if(opt & OPT_PORT) | 1965 | if (opt & OPT_PORT) |
1970 | config->port = bb_xgetlarg(s_port, 10, 1, 0xffff); | 1966 | config->port = bb_xgetlarg(s_port, 10, 1, 0xffff); |
1971 | #ifdef CONFIG_FEATURE_HTTPD_SETUID | 1967 | #ifdef CONFIG_FEATURE_HTTPD_SETUID |
1972 | if(opt & OPT_SETUID) { | 1968 | if (opt & OPT_SETUID) { |
1973 | char *e; | 1969 | char *e; |
1974 | 1970 | ||
1975 | uid = strtol(s_uid, &e, 0); | 1971 | uid = strtol(s_uid, &e, 0); |
1976 | if(*e != '\0') { | 1972 | if (*e != '\0') { |
1977 | /* not integer */ | 1973 | /* not integer */ |
1978 | uid = bb_xgetpwnam(s_uid); | 1974 | uid = bb_xgetpwnam(s_uid); |
1975 | } | ||
1979 | } | 1976 | } |
1980 | } | ||
1981 | #endif | 1977 | #endif |
1982 | #endif | 1978 | #endif |
1983 | 1979 | ||
1984 | xchdir(home_httpd); | 1980 | xchdir(home_httpd); |
1985 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1981 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
1986 | server = openServer(); | 1982 | server = openServer(); |
1987 | # ifdef CONFIG_FEATURE_HTTPD_SETUID | 1983 | # ifdef CONFIG_FEATURE_HTTPD_SETUID |
1988 | /* drop privileges */ | 1984 | /* drop privileges */ |
1989 | if(uid > 0) | 1985 | if (uid > 0) |
1990 | xsetuid(uid); | 1986 | xsetuid(uid); |
1991 | # endif | 1987 | # endif |
1992 | #endif | 1988 | #endif |
1993 | 1989 | ||
1994 | #ifdef CONFIG_FEATURE_HTTPD_CGI | 1990 | #ifdef CONFIG_FEATURE_HTTPD_CGI |
1995 | { | 1991 | { |
1996 | char *p = getenv("PATH"); | 1992 | char *p = getenv("PATH"); |
1997 | if(p) { | 1993 | if (p) { |
1998 | p = xstrdup(p); | 1994 | p = xstrdup(p); |
1999 | } | 1995 | } |
2000 | clearenv(); | 1996 | clearenv(); |
2001 | if(p) | 1997 | if (p) |
2002 | setenv("PATH", p, 1); | 1998 | setenv("PATH", p, 1); |
2003 | # ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 1999 | # ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
2004 | addEnvPort("SERVER"); | 2000 | addEnvPort("SERVER"); |
2005 | # endif | 2001 | # endif |
2006 | } | 2002 | } |
2007 | #endif | 2003 | #endif |
2008 | 2004 | ||
2009 | #ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP | 2005 | #ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP |
2010 | sighup_handler(0); | 2006 | sighup_handler(0); |
2011 | #else | 2007 | #else |
2012 | parse_conf(default_path_httpd_conf, FIRST_PARSE); | 2008 | parse_conf(default_path_httpd_conf, FIRST_PARSE); |
2013 | #endif | 2009 | #endif |
2014 | 2010 | ||
2015 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD | 2011 | #ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD |
2016 | # if !DEBUG | 2012 | # if !DEBUG |
2017 | xdaemon(1, 0); /* don`t change curent directory */ | 2013 | xdaemon(1, 0); /* don`t change curent directory */ |
2018 | # endif | 2014 | # endif |
2019 | return miniHttpd(server); | 2015 | return miniHttpd(server); |
2020 | #else | 2016 | #else |
2021 | return miniHttpd(); | 2017 | return miniHttpd(); |
2022 | #endif | 2018 | #endif |
2023 | } | 2019 | } |