source:
branches/fc19-dev/server/common/patches/httpd-suexec-scripts.patch
@
2422
Last change on this file since 2422 was 2422, checked in by tboning, 11 years ago | |
---|---|
File size: 9.7 KB |
-
configure.in
From 8445788d68230b2e18739166f4c3ae6434038421 Mon Sep 17 00:00:00 2001 From: Alexander Chernyakhovsky <achernya@mit.edu> Date: Fri, 3 May 2013 21:38:58 -0400 Subject: [PATCH 1/4] 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 d93f78c..14faccf 100644
a b AC_ARG_WITH(suexec-userdir, 720 720 APACHE_HELP_STRING(--with-suexec-userdir,User subdirectory),[ 721 721 AC_DEFINE_UNQUOTED(AP_USERDIR_SUFFIX, "$withval", [User subdirectory] ) ] ) 722 722 723 AC_ARG_WITH(suexec-trusteddir, 724 APACHE_HELP_STRING(--with-suexec-trusteddir,Trusted SuExec directory),[ 725 AC_DEFINE_UNQUOTED(AP_TRUSTED_DIRECTORY, "$withval", [Trusted SuExec directory] ) ] ) 726 723 727 AC_ARG_WITH(suexec-docroot, 724 728 APACHE_HELP_STRING(--with-suexec-docroot,SuExec root directory),[ 725 729 AC_DEFINE_UNQUOTED(AP_DOC_ROOT, "$withval", [SuExec root directory] ) ] ) -
support/suexec.c
diff --git a/support/suexec.c b/support/suexec.c index 5b6b254..e377042 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) 264 268 environ = cleanenv; 265 269 } 266 270 271 static const char *static_extensions[] = { 272 "html", 273 "css", 274 "gif", 275 "jpg", 276 "png", 277 "htm", 278 "jpeg", 279 "js", 280 "ico", 281 "xml", 282 "xsl", 283 "tiff", 284 "tif", 285 "tgz", 286 "tar", 287 "jar", 288 "zip", 289 "pdf", 290 "ps", 291 "doc", 292 "xls", 293 "ppt", 294 "dot", 295 "docx", 296 "dotx", 297 "docm", 298 "dotm", 299 "xlt", 300 "xla", 301 "xlsx", 302 "xltx", 303 "xlsm", 304 "xltm", 305 "xlam", 306 "xlsb", 307 "pot", 308 "pps", 309 "ppa", 310 "pptx", 311 "potx", 312 "ppsx", 313 "ppam", 314 "pptm", 315 "potm", 316 "ppsm", 317 "swf", 318 "mp3", 319 "mov", 320 "wmv", 321 "mpg", 322 "mpeg", 323 "avi", 324 "il", 325 "xhtml", 326 "svg", 327 "xaml", 328 "xap", 329 "wav", 330 "mid", 331 "midi", 332 "ttf", 333 "otf", 334 "odc", 335 "odb", 336 "odf", 337 "odg", 338 "otg", 339 "odi", 340 "odp", 341 "otp", 342 "ods", 343 "ots", 344 "odt", 345 "odm", 346 "ott", 347 "oth", 348 NULL 349 }; 350 351 static int is_static_extension(const char *file) 352 { 353 const char *extension = strrchr(file, '.'); 354 const char **p; 355 if (extension == NULL) return 0; 356 for (p = static_extensions; *p; ++p) { 357 if (strcasecmp(extension + 1, *p) == 0) return 1; 358 } 359 return 0; 360 } 361 362 static int is_php_extension(const char *file) 363 { 364 const char *extension = strrchr(file, '.'); 365 if (extension == NULL) return 0; 366 return strcmp(extension + 1, "php") == 0; 367 } 368 267 369 int main(int argc, char *argv[]) 268 370 { 269 371 int userdir = 0; /* ~userdir flag */ 372 int trusteddir = 0; /* TRUSTED_DIRECTORY flag */ 270 373 uid_t uid; /* user information */ 271 374 gid_t gid; /* target group placeholder */ 272 375 char *target_uname; /* target user name */ … … int main(int argc, char *argv[]) 286 389 * Start with a "clean" environment 287 390 */ 288 391 clean_env(); 392 setenv("JAVA_TOOL_OPTIONS", "-Xmx128M", 1); /* scripts.mit.edu local hack */ 289 393 290 394 /* 291 395 * Check existence/validity of the UID of the user … … int main(int argc, char *argv[]) 369 473 #endif /*_OSD_POSIX*/ 370 474 371 475 /* 476 * First check if this is an absolute path to the directory 477 * of trusted executables. These are supposed to be security 478 * audited to check parameters and validity on their own... 479 */ 480 if (strstr(cmd, AP_TRUSTED_DIRECTORY) == cmd) { 481 if (strstr(cmd, "/../") != NULL) { 482 log_err("invalid command (%s)\n", cmd); 483 exit(104); 484 } 485 trusteddir = 1; 486 goto TRUSTED_DIRECTORY; 487 } 488 489 /* 372 490 * Check for a leading '/' (absolute path) in the command to be executed, 373 491 * or attempts to back up out of the current directory, 374 492 * to protect against attacks. If any are … … int main(int argc, char *argv[]) 390 508 userdir = 1; 391 509 } 392 510 511 TRUSTED_DIRECTORY: 393 512 /* 394 513 * Error out if the target username is invalid. 395 514 */ … … int main(int argc, char *argv[]) 471 590 * Error out if attempt is made to execute as root or as 472 591 * a UID less than AP_UID_MIN. Tsk tsk. 473 592 */ 474 if ((uid == 0) || (uid < AP_UID_MIN )) {593 if ((uid == 0) || (uid < AP_UID_MIN && uid != 102)) { /* uid 102 = signup */ 475 594 log_err("cannot run as forbidden uid (%lu/%s)\n", (unsigned long)uid, cmd); 476 595 exit(107); 477 596 } … … int main(int argc, char *argv[]) 503 622 log_err("failed to setuid (%lu: %s)\n", (unsigned long)uid, cmd); 504 623 exit(110); 505 624 } 625 setenv("HOME", target_homedir, 1); 506 626 507 627 /* 508 628 * Get the current working directory, as well as the proper … … int main(int argc, char *argv[]) 525 645 log_err("cannot get docroot information (%s)\n", target_homedir); 526 646 exit(112); 527 647 } 648 size_t expected_len = strlen(target_homedir)+1+strlen(AP_USERDIR_SUFFIX)+1; 649 char *expected = malloc(expected_len); 650 snprintf(expected, expected_len, "%s/%s", target_homedir, AP_USERDIR_SUFFIX); 651 if (strncmp(cwd, expected, expected_len-1) != 0) { 652 log_err("error: file's directory not a subdirectory of user's home directory (%s, %s)\n", cwd, expected); 653 exit(114); 654 } 655 } 656 else if (trusteddir) { 657 if (((chdir(AP_TRUSTED_DIRECTORY)) != 0) || 658 ((getcwd(dwd, AP_MAXPATH)) == NULL) | 659 ((chdir(cwd)) != 0)) { 660 log_err("cannot get docroot information (%s)\n", AP_TRUSTED_DIRECTORY); 661 exit(112); 662 } 528 663 } 529 664 else { 530 665 if (((chdir(AP_DOC_ROOT)) != 0) || … … int main(int argc, char *argv[]) 551 686 /* 552 687 * Error out if cwd is writable by others. 553 688 */ 689 #if 0 554 690 if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) { 555 691 log_err("directory is writable by others: (%s)\n", cwd); 556 692 exit(116); 557 693 } 694 #endif 558 695 559 696 /* 560 697 * Error out if we cannot stat the program. 561 698 */ 562 if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {699 if (((lstat(cmd, &prg_info)) != 0) /*|| (S_ISLNK(prg_info.st_mode))*/) { 563 700 log_err("cannot stat program: (%s)\n", cmd); 564 701 exit(117); 565 702 } … … int main(int argc, char *argv[]) 567 704 /* 568 705 * Error out if the program is writable by others. 569 706 */ 707 #if 0 570 708 if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) { 571 709 log_err("file is writable by others: (%s/%s)\n", cwd, cmd); 572 710 exit(118); 573 711 } 712 #endif 574 713 575 714 /* 576 715 * Error out if the file is setuid or setgid. … … int main(int argc, char *argv[]) 584 723 * Error out if the target name/group is different from 585 724 * the name/group of the cwd or the program. 586 725 */ 726 #if 0 587 727 if ((uid != dir_info.st_uid) || 588 728 (gid != dir_info.st_gid) || 589 729 (uid != prg_info.st_uid) || … … int main(int argc, char *argv[]) 595 735 (unsigned long)prg_info.st_uid, (unsigned long)prg_info.st_gid); 596 736 exit(120); 597 737 } 738 #endif 598 739 /* 599 740 * Error out if the program is not executable for the user. 600 741 * Otherwise, she won't find any error in the logs except for 601 742 * "[error] Premature end of script headers: ..." 602 743 */ 603 if (!(prg_info.st_mode & S_IXUSR)) { 744 if (!is_static_extension(cmd) && !is_php_extension(cmd) && 745 !(prg_info.st_mode & S_IXUSR)) { 604 746 log_err("file has no execute permission: (%s/%s)\n", cwd, cmd); 605 747 exit(121); 606 748 } … … int main(int argc, char *argv[]) 649 791 /* 650 792 * Execute the command, replacing our image with its own. 651 793 */ 794 if (is_static_extension(cmd)) { 795 if (setenv("PATH_TRANSLATED", cmd, 1) != 0) { 796 log_err("setenv failed\n"); 797 exit(255); 798 } 799 execl(STATIC_CAT_PATH, STATIC_CAT_PATH, (const char *)NULL); 800 log_err("(%d)%s: static-cat exec failed (%s)\n", errno, strerror(errno), STATIC_CAT_PATH); 801 exit(255); 802 } 803 if (is_php_extension(cmd)) { 804 setenv("PHPRC", ".", 1); 805 argv[1] = PHP_PATH; 806 argv[2] = "-f"; 807 /* 808 * argv[3] is the command to run. argv[4] is either an argument or 809 * already null. We don't want to pass any arguments through from 810 * Apache (since they're untrusted), so we chop off the remainder 811 * of argv here. 812 */ 813 argv[4] = 0; 814 execv(PHP_PATH, &argv[1]); 815 log_err("(%d)%s: php exec failed (%s)\n", errno, strerror(errno), argv[1]); 816 exit(255); 817 } 652 818 #ifdef NEED_HASHBANG_EMUL 653 819 /* We need the #! emulation when we want to execute scripts */ 654 820 {
Note: See TracBrowser
for help on using the repository browser.