source:
trunk/server/common/patches/httpd-suexec-scripts.patch
@
2591
Last change on this file since 2591 was 2591, checked in by achernya, 10 years ago | |
---|---|
File size: 9.7 KB |
-
configure.in
From 427d432a56df94d69a11cc438b08adb070615005 Mon Sep 17 00:00:00 2001 From: Alexander Chernyakhovsky <achernya@mit.edu> Date: Fri, 3 May 2013 21:38:58 -0400 Subject: [PATCH] Add scripts-specific support to suexec This patch make suexec aware of static-cat, Scripts' tool to serve static content out of AFS. Specifically, this introduces a whitelist of extensions for which suexec is supposed to invoke static-cat as a content-handler. Additionally, this patch also sets JAVA_TOOL_OPTIONS, to allow the JVM to start up in Scripts' limited memory environment. Furthermore, this patch deals with some of suexec's paranoia being incorrect in an AFS world, by ignoring some of the irrelevant stat results. Finally, add support for invoking php-cgi for php files, in a safe manner that will strip arguments passed by Apache to php-cgi. --- configure.in | 4 ++ support/suexec.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 811aace..a95349f 100644
a b AC_ARG_WITH(suexec-userdir, 721 721 APACHE_HELP_STRING(--with-suexec-userdir,User subdirectory),[ 722 722 AC_DEFINE_UNQUOTED(AP_USERDIR_SUFFIX, "$withval", [User subdirectory] ) ] ) 723 723 724 AC_ARG_WITH(suexec-trusteddir, 725 APACHE_HELP_STRING(--with-suexec-trusteddir,Trusted SuExec directory),[ 726 AC_DEFINE_UNQUOTED(AP_TRUSTED_DIRECTORY, "$withval", [Trusted SuExec directory] ) ] ) 727 724 728 AC_ARG_WITH(suexec-docroot, 725 729 APACHE_HELP_STRING(--with-suexec-docroot,SuExec root directory),[ 726 730 AC_DEFINE_UNQUOTED(AP_DOC_ROOT, "$withval", [SuExec root directory] ) ] ) -
support/suexec.c
diff --git a/support/suexec.c b/support/suexec.c index 32e7320..3a4d802 100644
a b 30 30 * 31 31 */ 32 32 33 #define STATIC_CAT_PATH "/usr/bin/static-cat" 34 #define PHP_PATH "/usr/bin/php-cgi" 35 33 36 #include "apr.h" 34 37 #include "ap_config.h" 35 38 #include "suexec.h" … … static const char *const safe_env_lst[] = 92 95 { 93 96 /* variable name starts with */ 94 97 "HTTP_", 98 "HTTPS_", 95 99 "SSL_", 96 100 97 101 /* variable name is */ … … static void clean_env(void) 268 272 environ = cleanenv; 269 273 } 270 274 275 static const char *static_extensions[] = { 276 "html", 277 "css", 278 "gif", 279 "jpg", 280 "png", 281 "htm", 282 "jpeg", 283 "js", 284 "ico", 285 "xml", 286 "xsl", 287 "tiff", 288 "tif", 289 "tgz", 290 "tar", 291 "jar", 292 "zip", 293 "pdf", 294 "ps", 295 "doc", 296 "xls", 297 "ppt", 298 "dot", 299 "docx", 300 "dotx", 301 "docm", 302 "dotm", 303 "xlt", 304 "xla", 305 "xlsx", 306 "xltx", 307 "xlsm", 308 "xltm", 309 "xlam", 310 "xlsb", 311 "pot", 312 "pps", 313 "ppa", 314 "pptx", 315 "potx", 316 "ppsx", 317 "ppam", 318 "pptm", 319 "potm", 320 "ppsm", 321 "swf", 322 "mp3", 323 "mov", 324 "wmv", 325 "mpg", 326 "mpeg", 327 "avi", 328 "il", 329 "xhtml", 330 "svg", 331 "xaml", 332 "xap", 333 "wav", 334 "mid", 335 "midi", 336 "ttf", 337 "otf", 338 "odc", 339 "odb", 340 "odf", 341 "odg", 342 "otg", 343 "odi", 344 "odp", 345 "otp", 346 "ods", 347 "ots", 348 "odt", 349 "odm", 350 "ott", 351 "oth", 352 NULL 353 }; 354 355 static int is_static_extension(const char *file) 356 { 357 const char *extension = strrchr(file, '.'); 358 const char **p; 359 if (extension == NULL) return 0; 360 for (p = static_extensions; *p; ++p) { 361 if (strcasecmp(extension + 1, *p) == 0) return 1; 362 } 363 return 0; 364 } 365 366 static int is_php_extension(const char *file) 367 { 368 const char *extension = strrchr(file, '.'); 369 if (extension == NULL) return 0; 370 return strcmp(extension + 1, "php") == 0; 371 } 372 271 373 int main(int argc, char *argv[]) 272 374 { 273 375 int userdir = 0; /* ~userdir flag */ 376 int trusteddir = 0; /* TRUSTED_DIRECTORY flag */ 274 377 uid_t uid; /* user information */ 275 378 gid_t gid; /* target group placeholder */ 276 379 char *target_uname; /* target user name */ … … int main(int argc, char *argv[]) 290 393 * Start with a "clean" environment 291 394 */ 292 395 clean_env(); 396 setenv("JAVA_TOOL_OPTIONS", "-Xmx128M", 1); /* scripts.mit.edu local hack */ 293 397 294 398 /* 295 399 * Check existence/validity of the UID of the user … … int main(int argc, char *argv[]) 373 477 #endif /*_OSD_POSIX*/ 374 478 375 479 /* 480 * First check if this is an absolute path to the directory 481 * of trusted executables. These are supposed to be security 482 * audited to check parameters and validity on their own... 483 */ 484 if (strstr(cmd, AP_TRUSTED_DIRECTORY) == cmd) { 485 if (strstr(cmd, "/../") != NULL) { 486 log_err("invalid command (%s)\n", cmd); 487 exit(104); 488 } 489 trusteddir = 1; 490 goto TRUSTED_DIRECTORY; 491 } 492 493 /* 376 494 * Check for a leading '/' (absolute path) in the command to be executed, 377 495 * or attempts to back up out of the current directory, 378 496 * to protect against attacks. If any are … … int main(int argc, char *argv[]) 394 512 userdir = 1; 395 513 } 396 514 515 TRUSTED_DIRECTORY: 397 516 /* 398 517 * Error out if the target username is invalid. 399 518 */ … … int main(int argc, char *argv[]) 482 601 * Error out if attempt is made to execute as root or as 483 602 * a UID less than AP_UID_MIN. Tsk tsk. 484 603 */ 485 if ((uid == 0) || (uid < AP_UID_MIN )) {604 if ((uid == 0) || (uid < AP_UID_MIN && uid != 102)) { /* uid 102 = signup */ 486 605 log_err("cannot run as forbidden uid (%lu/%s)\n", (unsigned long)uid, cmd); 487 606 exit(107); 488 607 } … … int main(int argc, char *argv[]) 514 633 log_err("failed to setuid (%lu: %s)\n", (unsigned long)uid, cmd); 515 634 exit(110); 516 635 } 636 setenv("HOME", target_homedir, 1); 517 637 518 638 /* 519 639 * Get the current working directory, as well as the proper … … int main(int argc, char *argv[]) 536 656 log_err("cannot get docroot information (%s)\n", target_homedir); 537 657 exit(112); 538 658 } 659 size_t expected_len = strlen(target_homedir)+1+strlen(AP_USERDIR_SUFFIX)+1; 660 char *expected = malloc(expected_len); 661 snprintf(expected, expected_len, "%s/%s", target_homedir, AP_USERDIR_SUFFIX); 662 if (strncmp(cwd, expected, expected_len-1) != 0) { 663 log_err("error: file's directory not a subdirectory of user's home directory (%s, %s)\n", cwd, expected); 664 exit(114); 665 } 666 } 667 else if (trusteddir) { 668 if (((chdir(AP_TRUSTED_DIRECTORY)) != 0) || 669 ((getcwd(dwd, AP_MAXPATH)) == NULL) | 670 ((chdir(cwd)) != 0)) { 671 log_err("cannot get docroot information (%s)\n", AP_TRUSTED_DIRECTORY); 672 exit(112); 673 } 539 674 } 540 675 else { 541 676 if (((chdir(AP_DOC_ROOT)) != 0) || … … int main(int argc, char *argv[]) 562 697 /* 563 698 * Error out if cwd is writable by others. 564 699 */ 700 #if 0 565 701 if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) { 566 702 log_err("directory is writable by others: (%s)\n", cwd); 567 703 exit(116); 568 704 } 705 #endif 569 706 570 707 /* 571 708 * Error out if we cannot stat the program. 572 709 */ 573 if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {710 if (((lstat(cmd, &prg_info)) != 0) /*|| (S_ISLNK(prg_info.st_mode))*/) { 574 711 log_err("cannot stat program: (%s)\n", cmd); 575 712 exit(117); 576 713 } … … int main(int argc, char *argv[]) 578 715 /* 579 716 * Error out if the program is writable by others. 580 717 */ 718 #if 0 581 719 if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) { 582 720 log_err("file is writable by others: (%s/%s)\n", cwd, cmd); 583 721 exit(118); 584 722 } 723 #endif 585 724 586 725 /* 587 726 * Error out if the file is setuid or setgid. … … int main(int argc, char *argv[]) 595 734 * Error out if the target name/group is different from 596 735 * the name/group of the cwd or the program. 597 736 */ 737 #if 0 598 738 if ((uid != dir_info.st_uid) || 599 739 (gid != dir_info.st_gid) || 600 740 (uid != prg_info.st_uid) || … … int main(int argc, char *argv[]) 606 746 (unsigned long)prg_info.st_uid, (unsigned long)prg_info.st_gid); 607 747 exit(120); 608 748 } 749 #endif 609 750 /* 610 751 * Error out if the program is not executable for the user. 611 752 * Otherwise, she won't find any error in the logs except for 612 753 * "[error] Premature end of script headers: ..." 613 754 */ 614 if (!(prg_info.st_mode & S_IXUSR)) { 755 if (!is_static_extension(cmd) && !is_php_extension(cmd) && 756 !(prg_info.st_mode & S_IXUSR)) { 615 757 log_err("file has no execute permission: (%s/%s)\n", cwd, cmd); 616 758 exit(121); 617 759 } … … int main(int argc, char *argv[]) 660 802 /* 661 803 * Execute the command, replacing our image with its own. 662 804 */ 805 if (is_static_extension(cmd)) { 806 if (setenv("PATH_TRANSLATED", cmd, 1) != 0) { 807 log_err("setenv failed\n"); 808 exit(255); 809 } 810 execl(STATIC_CAT_PATH, STATIC_CAT_PATH, (const char *)NULL); 811 log_err("(%d)%s: static-cat exec failed (%s)\n", errno, strerror(errno), STATIC_CAT_PATH); 812 exit(255); 813 } 814 if (is_php_extension(cmd)) { 815 setenv("PHPRC", ".", 1); 816 argv[1] = PHP_PATH; 817 argv[2] = "-f"; 818 /* 819 * argv[3] is the command to run. argv[4] is either an argument or 820 * already null. We don't want to pass any arguments through from 821 * Apache (since they're untrusted), so we chop off the remainder 822 * of argv here. 823 */ 824 argv[4] = 0; 825 execv(PHP_PATH, &argv[1]); 826 log_err("(%d)%s: php exec failed (%s)\n", errno, strerror(errno), argv[1]); 827 exit(255); 828 } 663 829 #ifdef NEED_HASHBANG_EMUL 664 830 /* We need the #! emulation when we want to execute scripts */ 665 831 {
Note: See TracBrowser
for help on using the repository browser.