--- suexec.c.orig	Mon Dec 01 00:47:31 2008
+++ suexec.c	Sat Dec 17 04:21:15 2011
@@ -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 :-)
@@ -96,6 +100,7 @@
     /* variable name starts with */
     "HTTP_",
     "SSL_",
+    "CGIENV_",
 
     /* variable name is */
     "AUTH_TYPE=",
@@ -143,6 +148,53 @@
     NULL
 };
 
+/* Ituki Kirihara/NI Add */
+#ifdef CHROOT_DIR
+#if 0
+/*
+  chroot_dir_list is NULL terminated chroot-directory list.
+  PLEASE UPDATE THIS CODE!!
+
+  example.
+  
+  if chroot to /home only then (example, user home is /home/ituki, /home/www, /home/til)
+  chroot_dir_list update next code.
+
+    char *chroot_dir_list[] = {
+        "/home/",
+        NULL
+    };
+
+  if chroot to /home/realFriend, /home/virtualFriend and /home/other then
+  chdir_dir_list update next code.
+
+    char *chroot_dir_list[] = {
+        "/home/realFriend/",
+        "/home/virtualFriend/",
+        "/home/other/",
+        NULL
+    };
+*/
+#endif
+/* chroot_dir list, require last char is "/" */
+/* this is a sample. chroot to /home/cgi and /home/cgi2. */
+/* PLEASE THANGE THIS! */
+char *chroot_dir_list[] = {
+    "/home/cgi/",
+    "/home/cgi2/",
+    NULL
+};
+/* end change yourself. */
+
+/* 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(int is_error, const char *fmt, va_list ap)
 {
@@ -245,6 +297,35 @@
     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){
+             if (strncmp(env,"redirect:",9) == 0) continue; /* skip */
+             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             */
@@ -263,6 +344,11 @@
     struct group *gr;       /* group entry holder        */
     struct stat dir_info;   /* directory info holder     */
     struct stat prg_info;   /* program info holder       */
+#ifdef CHROOT_DIR
+    int chroot_on = 0;      /* if chroot,then 1 else 0   */
+    char** chroot_path = 0; /* chroot path temp          */
+    size_t chroot_dir_len = 0; /* chroot directory len   */
+#endif
 
     /*
      * Start with a "clean" environment
@@ -466,6 +552,58 @@
         exit(108);
     }
 
+   /* 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);
+                    }
+                }
+                /* current directory in *chroot_path. */
+                if(chroot(*chroot_path) != 0){
+                    log_err("cannot exec chroot\n");
+                    exit(111);
+                }
+                log_no_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 */
+
     /*
      * Change UID/GID here so that the following tests work over NFS.
      *
@@ -508,12 +646,35 @@
         }
     }
     else {
+        /* Ituki Kirihara/NI Change */
+#ifdef CHROOT_DIR
+        if (chroot_on){
+            /* current dir in AP_DOC_ROOT (chroot dir in AP_DOC_ROOT) */
+            /* chdir "/" eq REAL(no chroot) AP_DOC_ROOT/subpath . */
+            /* REAL(no chroot) cwd is AP_DOC_ROOT/fullpath */
+            if (((chdir("/")) != 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);
+            }
+        }
+#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) {
