Patch gridmapdir code into gsexec
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 26 May 2005 21:14:21 +0000 (21:14 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 26 May 2005 21:14:21 +0000 (21:14 +0000)
org.gridsite.core/CHANGES
org.gridsite.core/doc/httpd-fileserver.conf
org.gridsite.core/doc/httpd-webserver.conf
org.gridsite.core/src/Makefile
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/gsexec.c
org.gridsite.core/src/gsexec.h

index 9b86237..a9a305e 100644 (file)
@@ -1,3 +1,7 @@
+* Thu May 26 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Include gsexec, a drop-in replacement for suexec,
+  which can do suexec execution of CGI programs or
+  pool-account mapping based on client DN.
 * Tue May 24 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
 - ==== GridSite version 1.1.9 ====
 * Mon Apr 25 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
index 9bd51e2..192d9e3 100644 (file)
@@ -123,6 +123,8 @@ Listen 80
 # Secured and possibly authenticated HTTPS on port 443
 ######################################################################
 Listen 443
+SSLSessionCache         dbm:/var/cache/mod_ssl/scache
+SSLSessionCacheTimeout  300
 <VirtualHost *:443>
  
 SSLEngine               on
@@ -130,8 +132,6 @@ SSLCertificateFile      /etc/grid-security/hostcert.pem
 SSLCertificateKeyFile   /etc/grid-security/hostkey.pem
 SSLCACertificatePath    /etc/grid-security/certificates
 #SSLCARevocationPath    YOUR CRL DIRECTORY WOULD GO HERE
-SSLSessionCache         dbm:/var/cache/mod_ssl/scache
-SSLSessionCacheTimeout  300
 SSLVerifyClient         optional
 SSLVerifyDepth          10
 SSLOptions              +ExportCertData +StdEnvVars
index da332a0..e2e03ff 100644 (file)
@@ -153,6 +153,8 @@ ScriptAlias /real-gridsite-admin.cgi /usr/sbin/real-gridsite-admin.cgi
 # Secured and possibly authenticated HTTPS on port 443
 ######################################################################
 Listen 443
+SSLSessionCache         dbm:/var/cache/mod_ssl/scache
+SSLSessionCacheTimeout  300
 <VirtualHost *:443>
  
 SSLEngine               on
@@ -160,8 +162,6 @@ SSLCertificateFile      /etc/grid-security/hostcert.pem
 SSLCertificateKeyFile   /etc/grid-security/hostkey.pem
 SSLCACertificatePath    /etc/grid-security/certificates
 #SSLCARevocationPath    YOUR CRL DIRECTORY WOULD GO HERE
-SSLSessionCache         dbm:/var/cache/mod_ssl/scache
-SSLSessionCacheTimeout  300
 SSLVerifyClient         optional
 SSLVerifyDepth          10
 SSLOptions              +ExportCertData +StdEnvVars
index bd14ba4..234cd8a 100644 (file)
@@ -136,7 +136,7 @@ libgridsite_globus.a: libgridsite.a
 
 endif
 
-gsexec:        gsexec.c 
+gsexec:        gsexec.c gsexec.h
        gcc -DVERSION=\"$(PATCH_VERSION)\" -I/usr/include/httpd \
            -I/usr/include/apr-0 \
            -o gsexec gsexec.c
index ec2b385..942dd7e 100644 (file)
@@ -1412,7 +1412,7 @@ int GRSTx509CacheProxy(char *proxydir, char *delegation_id,
       return GRST_RET_FAILED;
     }
 
-  fprintf(stderr, "\n\n\n\n PROXYCHAIN = \n %s", proxychain);
+//  fprintf(stderr, "\n\n\n\n PROXYCHAIN = \n %s", proxychain);
   if (GRSTx509StringToChain(&certstack, proxychain) != GRST_RET_OK)
                                                     return GRST_RET_FAILED;
 
index a9abf9f..eeec524 100644 (file)
@@ -245,10 +245,280 @@ static void clean_env(void)
     environ = cleanenv;
 }
 
+/* Pool account functions */
+
+
+#include <utime.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+/******************************************************************************
+Function:   mapdir_otherlink
+Description:
+        find another link in map directory to the same inode as firstlink
+        and change the modification time of firstlink to now (so that we
+        always know when this pair was last used)
+        
+Parameters:
+        firstlink, the filename of the link we already know
+
+Returns:
+        a pointer to the other link's filename (without path) or NULL if none
+        found (this is malloc'd and will need freeing)
+
+******************************************************************************/
+static char *mapdir_otherlink(char *mapdir, char *firstlink)
+{
+     int            ret;
+     char           *firstlinkpath, *otherlinkdup, *otherlinkpath;
+     struct dirent  *mapdirentry;
+     DIR            *mapdirstream;
+     struct stat    statbuf;
+     ino_t          firstinode;
+
+     firstlinkpath = malloc(strlen(mapdir) + 2 + strlen(firstlink));
+     sprintf(firstlinkpath, "%s/%s", mapdir, firstlink);     
+     ret = stat(firstlinkpath, &statbuf);
+     free(firstlinkpath);   
+     if (ret != 0) return NULL;
+     if (statbuf.st_nlink != 2) return NULL;
+     
+     firstinode = statbuf.st_ino; /* save for comparisons */
+          
+     mapdirstream = opendir(mapdir);
+
+     if (mapdirstream != NULL)
+       {
+         while ((mapdirentry = readdir(mapdirstream)) != NULL)
+              {       
+                 if (strcmp(mapdirentry->d_name, firstlink) == 0) continue;
+           
+                 otherlinkpath = malloc(strlen(mapdir) + 2 + 
+                                        strlen(mapdirentry->d_name));
+                 sprintf(otherlinkpath, "%s/%s", mapdir, 
+                                            mapdirentry->d_name);
+
+                 ret = stat(otherlinkpath, &statbuf);     
+                 if ((ret == 0) && (statbuf.st_ino == firstinode))
+                   {
+                      utime(otherlinkpath, (struct utimbuf *) NULL);
+                      free(otherlinkpath);
+                      otherlinkdup = strdup(mapdirentry->d_name);
+                      closedir(mapdirstream);     
+                      return otherlinkdup;
+                   }
+                 else free(otherlinkpath);
+              }
+         
+         closedir(mapdirstream);     
+       }
+
+     return NULL;
+}
+
+/******************************************************************************
+Function:   mapdir_urlencode
+Description:
+        Convert string to URL encoded and return pointer to the encoded
+        version, obtained through malloc. Calling routine must free
+        this. Here "URL encoded" means anything other than an isalnum()
+        goes to %HH where HH is its ascii value in hex; also A-Z => a-z 
+        This name is suitable for filenames since no / or spaces.
+
+Parameters:
+        rawstring, the string to be converted
+
+Returns:
+        a pointer to the encoded string or NULL if the malloc failed
+
+******************************************************************************/
+static char *mapdir_urlencode(char *rawstring)
+{
+     int          encodedchar = 0, rawchar = 0;
+     char *       encodedstring;
+     
+     encodedstring = (char *) malloc(3 * strlen(rawstring) + 1);
+     
+     if (encodedstring == NULL) return (char *) NULL;
+
+     while (rawstring[rawchar] != '\0')
+          {
+            if (isalnum(rawstring[rawchar]))
+              {
+                encodedstring[encodedchar] = tolower(rawstring[rawchar]);
+                ++rawchar;
+                ++encodedchar;
+              }
+            else
+              {
+                sprintf(&encodedstring[encodedchar], "%%%02x", 
+                                               rawstring[rawchar]);
+                ++rawchar;
+                encodedchar = encodedchar + 3;
+              }         
+          }
+
+     encodedstring[encodedchar] = '\0';
+     
+     return encodedstring;
+}
+
+/******************************************************************************
+Function:   mapdir_newlease
+Description:
+        Search for an unleased local username to give to the X.509 DN or
+        directory key corresponding to encodedfilename, and then lease it.
+
+Parameters: 
+        encodedfilename, URL-encoded X.509 DN or directory key to associate
+         with an unlease pool username
+
+Returns:
+        no return value
+******************************************************************************/
+
+void mapdir_newlease(char *mapdir, char *encodedkey)
+{
+     int            ret;
+     char           *userfilename, *encodedfilename;
+     struct dirent  *mapdirentry;
+     DIR            *mapdirstream;
+     struct stat    statbuf;
+     
+     encodedfilename = malloc(strlen(mapdir) + (size_t) 2 + 
+                              strlen(encodedkey));
+     sprintf(encodedfilename, "%s/%s", mapdir, encodedkey);
+
+     mapdirstream = opendir(mapdir);
+
+     while ((mapdirentry = readdir(mapdirstream)) != NULL)
+     {
+       /* we dont want any files that dont look like acceptable usernames */
+       if ((*(mapdirentry->d_name) == '%') || 
+           (strcmp(mapdirentry->d_name, "root") == 0))   continue;
+       else if (*(mapdirentry->d_name) == '.')           continue;
+       else if (index(mapdirentry->d_name, '~') != NULL) continue;
+
+       userfilename = malloc(strlen(mapdir) + (size_t) 2 + 
+                             strlen(mapdirentry->d_name));
+       sprintf(userfilename, "%s/%s", mapdir, mapdirentry->d_name);
+       stat(userfilename, &statbuf);
+       
+       if (statbuf.st_nlink == 1) /* this one isnt leased yet */
+       {   
+           ret = link(userfilename, encodedfilename);
+           free(userfilename);
+           if (ret != 0) 
+           {
+               /* link failed: this is probably because a VERY lucky
+                  other process has obtained a lease for encodedfilename 
+                  while we were faffing around */
+               closedir(mapdirstream);
+               free(encodedfilename);
+               return;
+           }
+     
+           stat(encodedfilename, &statbuf);
+           if (statbuf.st_nlink > 2) 
+           {
+              /* two keys have grabbed the same username: back off */
+              unlink(encodedfilename);
+              continue;
+           }
+
+           closedir(mapdirstream);
+           free(encodedfilename);
+           return; /* link worked ok, so return */
+       }
+       else free(userfilename); /* already in use, try next one */
+     }
+     
+     closedir(mapdirstream);
+     free(encodedfilename);
+     return; /* no unleased names left: give up */     
+}
+     
+/******************************************************************************
+Function:   gridmapdir_userid
+Description:
+        This is equivalent to globus_gss_assist_gridmap but for the dynamic
+        user ids in the gridmapdir: maps a globusID to a local unix user id,
+        either one already leased, or calls gridmapdir_newlease() to obtain 
+        a new lease. This is called by globus_gss_assist_gridmap if the 
+        local user id in the static gridmap file begins . (for a dynamic id)
+
+Parameters: 
+        globusidp, globus client name who requested authentication 
+        usernameprefix, prefix of the local usernames which would 
+               be acceptable (or "\0" )
+        *userid returned userid name for local system. 
+
+Returns:
+       
+        0 on success
+        !=0 on failure
+
+******************************************************************************/
+
+
+
 int GRSTexecGetMapping(char **target_uname, char **target_gname, 
-                       char *map_x509dn
+                       char *mapdir, char *key
 {
-    return 1;
+    char *encodedkey;
+    
+    if (key[0] != '/') return 1; /* must be a proper X.509 DN or path */
+     
+    encodedkey = mapdir_urlencode(key);
+log_err("encodedkey=%s\n", encodedkey);
+    *target_uname = mapdir_otherlink(mapdir, encodedkey);
+log_err("*target_uname=%s\n", *target_uname);
+
+    if (*target_uname == NULL) /* maybe no lease yet */
+      {
+         mapdir_newlease(mapdir, encodedkey);
+         /* try making a lease */
+         
+         *target_uname = mapdir_otherlink(mapdir, encodedkey); 
+         /* check if there is a now a lease - possibly made by someone else */
+
+         if (*target_uname == NULL) 
+           {
+             free(encodedkey);
+             return 1; /* still no good */
+           }
+      }
+
+    free(encodedkey);
+    
+// nasty hack for now
+*target_gname = strdup(*target_uname);
+    
+    return 0;
+}
+
+void internal_server_error(void)
+{
+    /* use this when its probably an httpd.conf configuration error */
+
+    puts("Status: 500 Internal Server Error\n"
+         "Content-Type: text/html\n\n"
+         "<html><head><title>500 Internal Server Error</title></head>\n"
+         "<body><h1>Internal Server Error</h1></body></html>");
+}
+
+void forbidden_error(void)
+{
+    /* use this when unix file permissions/ownerships are probably wrong */
+
+    puts("Status: 403 Forbidden\n"
+         "Content-Type: text/html\n\n"
+         "<html><head><title>403 Forbidden</title></head>\n"
+         "<body><h1>Forbidden</h1></body></html>");
 }
 
 int main(int argc, char *argv[])
@@ -256,6 +526,8 @@ int main(int argc, char *argv[])
     int userdir = 0;        /* ~userdir flag             */
     uid_t uid;              /* user information          */
     gid_t gid;              /* target group placeholder  */
+    uid_t httpd_uid;       /* uid for AP_HTTPD_USER     */
+    gid_t httpd_gid;       /* uid for AP_HTTPD_GROUP    */
     char *mapping_type;            /* suexec / X509DN / directory */
     char *map_x509dn;      /* DN to use as pool acct. key */
     char *map_directory;    /* directory as pool acct. key */
@@ -286,6 +558,17 @@ int main(int argc, char *argv[])
     uid = getuid();
     if ((pw = getpwuid(uid)) == NULL) {
         log_err("crit: invalid uid: (%ld)\n", uid);
+        internal_server_error();
+        exit(102);
+    }
+    /*
+     * Check existence/validity of the GID of the user
+     * running this program.  Error out if invalid.
+     */
+    gid = getgid();
+    if ((gr = getgrgid(gid)) == NULL) {
+        log_err("crit: invalid gid: (%ld)\n", gid);
+        internal_server_error();
         exit(102);
     }
     /*
@@ -334,10 +617,12 @@ int main(int argc, char *argv[])
      */
     if (argc < 4) {
         log_err("too few arguments\n");
+        internal_server_error();
         exit(101);
     }
     
     mapping_type = getenv("GRST_EXEC_MAPPING");
+log_err("mapping_type=%s\n",mapping_type);
     if ((mapping_type    == NULL) ||
         (mapping_type[0] == '\0') ||
         (strcasecmp(mapping_type, "suexec") == 0))
@@ -348,18 +633,22 @@ int main(int argc, char *argv[])
       }
     else if (strcasecmp(mapping_type, "X509DN") == 0)
       {
+log_err("X509DN mapping type\n");
         map_x509dn = getenv("SSL_CLIENT_S_DN");
         if (map_x509dn == NULL)
           {
             log_err("No SSL_CLIENT_S_DN despite X509DN mapping\n");
+            internal_server_error();
             exit(151);
           }
 
-        if (GRSTexecGetMapping(&target_uname, &target_gname, map_x509dn) 
+        if (GRSTexecGetMapping(&target_uname, &target_gname, 
+                               GRST_EXECMAPDIR, map_x509dn) 
             != 0)
           {
             log_err("GRSTexecGetMapping() failed mapping \"%s\"\n", 
                     map_x509dn);
+            internal_server_error();
             exit(152);          
           }
       }
@@ -369,20 +658,24 @@ int main(int argc, char *argv[])
         if (map_directory == NULL)
           {
             log_err("No GRST_EXEC_MAP_DIR despite directory mapping\n");
+            internal_server_error();
             exit(153);
           }
 
-        if (GRSTexecGetMapping(&target_uname, &target_gname, map_directory) 
+        if (GRSTexecGetMapping(&target_uname, &target_gname, 
+                               GRST_EXECMAPDIR, map_directory) 
             != 0)
           {
             log_err("GRSTexecGetMapping() failed mapping \"%s\"\n", 
                     map_directory);
+            internal_server_error();
             exit(154);          
           }
       }
     else 
       {
         log_err("mapping type \"%s\" not recognised\n", mapping_type);
+        internal_server_error();
         exit(155);
       }
 
@@ -397,15 +690,33 @@ int main(int argc, char *argv[])
     /* User name comparisons are case insensitive on BS2000/OSD */
     if (strcasecmp(AP_HTTPD_USER, pw->pw_name)) {
         log_err("user mismatch (%s instead of %s)\n", pw->pw_name, AP_HTTPD_USER);
+        internal_server_error();
+        exit(103);
+    }
+    /* User name comparisons are case insensitive on BS2000/OSD */
+    if (strcasecmp(AP_HTTPD_GROUP, gr->gr_name)) {
+        log_err("group mismatch (%s instead of %s)\n", gr->gr_name, AP_HTTPD_GROUP);
+        internal_server_error();
         exit(103);
     }
 #else  /*_OSD_POSIX*/
     if (strcmp(AP_HTTPD_USER, pw->pw_name)) {
         log_err("user mismatch (%s instead of %s)\n", pw->pw_name, AP_HTTPD_USER);
+        internal_server_error();
+        exit(103);
+    }
+    if (strcmp(AP_HTTPD_GROUP, gr->gr_name)) {
+        log_err("group mismatch (%s instead of %s)\n", gr->gr_name, AP_HTTPD_GROUP);
+        internal_server_error();
         exit(103);
     }
 #endif /*_OSD_POSIX*/
 
+    /* Since they match (via name) save these for later */
+
+    httpd_uid = uid;
+    httpd_gid = gid;
+
     /*
      * Check for a leading '/' (absolute path) in the command to be executed,
      * or attempts to back up out of the current directory,
@@ -415,6 +726,7 @@ int main(int argc, char *argv[])
     if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3))
         || (strstr(cmd, "/../") != NULL)) {
         log_err("invalid command (%s)\n", cmd);
+        internal_server_error();
         exit(104);
     }
 
@@ -434,12 +746,14 @@ int main(int argc, char *argv[])
     if (strspn(target_uname, "1234567890") != strlen(target_uname)) {
         if ((pw = getpwnam(target_uname)) == NULL) {
             log_err("invalid target user name: (%s)\n", target_uname);
+            internal_server_error();
             exit(105);
         }
     }
     else {
         if ((pw = getpwuid(atoi(target_uname))) == NULL) {
             log_err("invalid target user id: (%s)\n", target_uname);
+            internal_server_error();
             exit(121);
         }
     }
@@ -450,6 +764,7 @@ int main(int argc, char *argv[])
     if (strspn(target_gname, "1234567890") != strlen(target_gname)) {
         if ((gr = getgrnam(target_gname)) == NULL) {
             log_err("invalid target group name: (%s)\n", target_gname);
+            internal_server_error();
             exit(106);
         }
         gid = gr->gr_gid;
@@ -472,6 +787,7 @@ int main(int argc, char *argv[])
         case -1:    /* Error */
             log_err("failed to setup bs2000 environment for user %s: %s\n",
                     target_uname, strerror(errno));
+            internal_server_error();
             exit(150);
         case 0:     /* Child */
             break;
@@ -482,6 +798,7 @@ int main(int argc, char *argv[])
             if (WIFSIGNALED(status)) {
                 kill (getpid(), WTERMSIG(status));
             }
+            internal_server_error();
             exit(WEXITSTATUS(status));
         }
     }
@@ -509,6 +826,7 @@ int main(int argc, char *argv[])
      */
     if ((uid == 0) || (uid < AP_UID_MIN)) {
         log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd);
+        internal_server_error();
         exit(107);
     }
 
@@ -518,6 +836,7 @@ int main(int argc, char *argv[])
      */
     if ((gid == 0) || (gid < AP_GID_MIN)) {
         log_err("cannot run as forbidden gid (%d/%s)\n", gid, cmd);
+        internal_server_error();
         exit(108);
     }
 
@@ -529,6 +848,7 @@ int main(int argc, char *argv[])
      */
     if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) {
         log_err("failed to setgid (%ld: %s)\n", gid, cmd);
+        internal_server_error();
         exit(109);
     }
 
@@ -537,6 +857,7 @@ int main(int argc, char *argv[])
      */
     if ((setuid(uid)) != 0) {
         log_err("failed to setuid (%ld: %s)\n", uid, cmd);
+        internal_server_error();
         exit(110);
     }
 
@@ -550,15 +871,18 @@ int main(int argc, char *argv[])
      */
     if (getcwd(cwd, AP_MAXPATH) == NULL) {
         log_err("cannot get current working directory\n");
+        internal_server_error();
         exit(111);
     }
 
+#if 0
     if (userdir) {
         if (((chdir(target_homedir)) != 0) ||
             ((chdir(AP_USERDIR_SUFFIX)) != 0) ||
             ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
             ((chdir(cwd)) != 0)) {
             log_err("cannot get docroot information (%s)\n", target_homedir);
+            internal_server_error();
             exit(112);
         }
     }
@@ -567,20 +891,24 @@ int main(int argc, char *argv[])
             ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
             ((chdir(cwd)) != 0)) {
             log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
+            internal_server_error();
             exit(113);
         }
     }
 
     if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
         log_err("command not in docroot (%s/%s)\n", cwd, cmd);
+        internal_server_error();
         exit(114);
     }
+#endif
 
     /*
      * Stat the cwd and verify it is a directory, or error out.
      */
     if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) {
         log_err("cannot stat directory: (%s)\n", cwd);
+        internal_server_error();
         exit(115);
     }
 
@@ -589,6 +917,7 @@ int main(int argc, char *argv[])
      */
     if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) {
         log_err("directory is writable by others: (%s)\n", cwd);
+        forbidden_error();
         exit(116);
     }
 
@@ -597,14 +926,16 @@ int main(int argc, char *argv[])
      */
     if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
         log_err("cannot stat program: (%s)\n", cmd);
+        forbidden_error();
         exit(117);
     }
 
     /*
      * Error out if the program is writable by others.
      */
-    if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) {
+    if (prg_info.st_mode & S_IWOTH) {
         log_err("file is writable by others: (%s/%s)\n", cwd, cmd);
+        forbidden_error();
         exit(118);
     }
 
@@ -613,24 +944,33 @@ int main(int argc, char *argv[])
      */
     if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) {
         log_err("file is either setuid or setgid: (%s/%s)\n", cwd, cmd);
+        forbidden_error();
         exit(119);
     }
 
     /*
      * Error out if the target name/group is different from
-     * the name/group of the cwd or the program.
+     * the name/group of the cwd or the program AND the name/group 
+     * of the cwd and program are not the AP_HTTPD_USER/AP_HTTPD_GROUP
+     * AND the name/group of the cwd and program are not root
      */
-    if ((uid != dir_info.st_uid) ||
-        (gid != dir_info.st_gid) ||
-        (uid != prg_info.st_uid) ||
-        (gid != prg_info.st_gid)) {
-        log_err("target uid/gid (%ld/%ld) mismatch "
-                "with directory (%ld/%ld) or program (%ld/%ld)\n",
-                uid, gid,
+    if (((uid != dir_info.st_uid) && (httpd_uid != dir_info.st_uid)
+                                  && (0 != dir_info.st_uid)) ||
+        ((gid != dir_info.st_gid) && (httpd_gid != dir_info.st_gid)
+                                  && (0 != dir_info.st_gid)) ||
+        ((uid != prg_info.st_uid) && (httpd_uid != prg_info.st_uid)
+                                  && (0 != prg_info.st_uid)) ||
+        ((gid != prg_info.st_gid) && (httpd_gid != prg_info.st_gid)
+                                  && (0 != prg_info.st_gid)))
+      {
+        log_err("target (%ld/%ld) or %s (%ld/%ld) or root (0/0) uid/gid "
+                "mismatch with directory (%ld/%ld) or program (%ld/%ld)\n",
+                uid, gid, AP_HTTPD_USER, httpd_uid, httpd_gid,
                 dir_info.st_uid, dir_info.st_gid,
                 prg_info.st_uid, prg_info.st_gid);
+        forbidden_error();
         exit(120);
-    }
+      }
     /*
      * Error out if the program is not executable for the user.
      * Otherwise, she won't find any error in the logs except for
@@ -638,6 +978,7 @@ int main(int argc, char *argv[])
      */
     if (!(prg_info.st_mode & S_IXUSR)) {
         log_err("file has no execute permission: (%s/%s)\n", cwd, cmd);
+        forbidden_error();
         exit(121);
     }
 
@@ -689,5 +1030,6 @@ int main(int argc, char *argv[])
      * Oh well, log the failure and error out.
      */
     log_err("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd);
+    internal_server_error();
     exit(255);
 }
index e76a3bb..b777421 100644 (file)
  *               this program.
  */
 #ifndef AP_HTTPD_USER
-#define AP_HTTPD_USER "www"
+#define AP_HTTPD_USER "apache"
+#endif
+
+/*
+ * HTTPD_GROUP -- Define as the group under which Apache normally
+ *                runs.  This is the only user allowed to execute
+ *                this program.
+ */
+#ifndef AP_HTTPD_GROUP
+#define AP_HTTPD_GROUP "apache"
 #endif
 
 /*
  * UID_MIN -- Define this as the lowest UID allowed to be a target user
- *            for suEXEC.  For most systems, 500 or 100 is common.
+ *            for suEXEC.  For most systems, 500 or 100 is common, but
+ *            99 will include user nobody on RedHat Linux systems.
  */
-#ifndef AP_UID_MIN
-#define AP_UID_MIN 100
+#ifdef AP_UID_MIN
+#undef AP_UID_MIN
 #endif
+#define AP_UID_MIN 99
 
 /*
  * GID_MIN -- Define this as the lowest GID allowed to be a target group
- *            for suEXEC.  For most systems, 100 is common.
+ *            for suEXEC.  For most systems, 100 is common, but 99 will
+ *            include group nobody on RedHat Linux systems.
  */
-#ifndef AP_GID_MIN
-#define AP_GID_MIN 100
+#ifdef AP_GID_MIN
+#undef AP_GID_MIN
 #endif
+#define AP_GID_MIN 99
 
 /*
  * USERDIR_SUFFIX -- Define to be the subdirectory under users' 
 #define AP_SAFE_PATH "/usr/local/bin:/usr/bin:/bin"
 #endif
 
+/*
+ * GRST_EXECMAPDIR -- Location of the gridmapdir-style directory of lock files
+ *
+ */
+#define GRST_EXECMAPDIR "/var/www/execmapdir"
+
 #endif /* _SUEXEC_H */