--- suexec.c.orig	Wed Jul 12 16:40:55 2006
+++ suexec.c	Mon Jun 22 18:14:02 2009
@@ -55,6 +55,10 @@
 #include <grp.h>
 #endif
 
+/* Ituki Kirihara/NI Add */
+#define CHROOT_DIR
+/* Ituki Kirihara/NI Add end */
+
 /*
  ***********************************************************************
  * There is no initgroups() in QNX, so I believe this is safe :-)
@@ -143,6 +147,23 @@
     NULL
 };
 
+/* Ituki Kirihara/NI Add */
+#ifdef CHROOT_DIR
+/* chroot_dir list, require last char is "/" */
+char *chroot_dir_list[] = {
+    "/home/cgi/",
+    "/home/cgi2/",
+    NULL
+};
+/* convert env chroot list */
+char *convertenv_chroot_lst[] = {
+    "DOCUMENT_ROOT",
+    "SCRIPT_FILENAME",
+    "PATH_TRANSLATED",
+    NULL
+};
+#endif
+/* Ituki Kirihara/NI Add end */
 
 static void err_output(const char *fmt, va_list ap)
 {
@@ -228,6 +249,32 @@
     environ = cleanenv;
 }
 
+/* Ituki Kirihara/NI Add */
+#ifdef CHROOT_DIR
+static int convertenv_chroot(const char* chroot_dir)
+{
+  char *env;
+  char *newenv;
+  char **lst;
+  size_t chroot_dir_len = strlen(chroot_dir);
+  for(lst = convertenv_chroot_lst; *lst != 0;++lst){
+      env = getenv(*lst);
+      if(env){
+          if(strncmp(env,chroot_dir,chroot_dir_len) != 0) return 1;
+          newenv = strdup(env);
+          if(!newenv) return 1;
+          if(setenv(*lst,newenv+chroot_dir_len-1,1) != 0){
+            free(newenv);
+            return 1;
+          }
+          free(newenv);
+      }
+  }
+  return 0;
+}
+#endif
+/* Ituki Kirihara/NI Add end */
+
 int main(int argc, char *argv[])
 {
     int userdir = 0;        /* ~userdir flag             */
@@ -246,6 +293,13 @@
     struct group *gr;       /* group entry holder        */
     struct stat dir_info;   /* directory info holder     */
     struct stat prg_info;   /* program info holder       */
+    /* Ituki Kirihara/NI Add */
+#ifdef CHROOT_DIR
+    int chroot_on = 0;      /* if chroot,then true */
+    char** chroot_path = 0;
+    size_t chroot_dir_len = 0;
+#endif
+    /* Ituki Kirihara/NI Add end */
 
     /*
      * Start with a "clean" environment
@@ -458,6 +512,57 @@
         exit(109);
     }
 
+    /* Ituki Kirihara/NI Add */
+#ifdef CHROOT_DIR
+    if (getcwd(cwd, AP_MAXPATH) == NULL) {
+        log_err("cannot get current working directory\n");
+        exit(111);
+    }
+    if (*cwd != '\0'){
+      /* chroot check */
+      chroot_path = chroot_dir_list;
+      while(*chroot_path != NULL){
+        chroot_dir_len = strlen(*chroot_path);
+        if (strncmp(cwd,*chroot_path,chroot_dir_len) == 0){
+          /* go chroot! */
+          if (userdir) {
+            if(strncmp(target_homedir,*chroot_path,chroot_dir_len) != 0){
+                log_err("home not in chroot\n");
+                exit(111);
+            }
+          }else{
+            if(strncmp(AP_DOC_ROOT,*chroot_path,sizeof(AP_DOC_ROOT)-1) != 0){
+                log_err("CHROOT_DIR not in AP_DOC_ROOT(compile configuration error)\n");
+                exit(111);
+            }
+          }
+          if(chroot(*chroot_path) != 0){
+            log_err("cannot exec chroot\n");
+            exit(111);
+          }
+          log_err("chroot exec on %s / uid: (%s/%s) gid: (%s/%s) cmd: %s\n",
+            *chroot_path,
+            target_uname, actual_uname,
+            target_gname, actual_gname,
+            cmd);
+          /* check dir move */
+          if (userdir) {
+            target_homedir += chroot_dir_len -1;
+          }
+          /* convert-env */
+          if(convertenv_chroot(*chroot_path)){
+            log_err("env convert fail.\n");
+            exit(111);
+          }
+          chroot_on = 1;
+          break;
+        }
+        ++chroot_path;
+      }
+    }
+#endif
+    /* Ituki Kirihara/NI Add end */
+
     /*
      * setuid() to the target user.  Error out on fail.
      */
@@ -489,12 +594,39 @@
         }
     }
     else {
+        /* Ituki Kirihara/NI Change */
+#ifdef CHROOT_DIR
+        /*
+        if (((chdir(AP_DOC_ROOT)) != 0) ||
+            ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+            ((chdir(cwd)) != 0)) {
+            log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
+            exit(113);
+        }
+        */
+        if (chroot_on){
+          /* current is in AP_DOC_ROOT */
+          if (((getcwd(dwd, AP_MAXPATH)) == NULL)) {
+              log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
+              exit(113);
+          }
+        }else{
+          if (((chdir(AP_DOC_ROOT)) != 0) ||
+              ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
+              ((chdir(cwd)) != 0)) {
+              log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
+              exit(113);
+          }
+        }
+#else
         if (((chdir(AP_DOC_ROOT)) != 0) ||
             ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
             ((chdir(cwd)) != 0)) {
             log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
             exit(113);
         }
+#endif
+      /* Ituki Kirihara/NI Change end */
     }
 
     if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
