randy       96/08/02 13:39:20

  Modified:    src       CHANGES http_conf_globals.h http_core.c
                        http_main.c httpd.h  util_script.c
  Log:
  Set Userid/Groupid execution of CGI based on User/Group directives
  or UserDir owner via ~user mapping.
  Reviewed by: Robert Thau, Jason Dour
  
  Revision  Changes    Path
  1.47      +7 -1      apache/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache/src/CHANGES,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -C3 -r1.46 -r1.47
  *** CHANGES   1996/07/29 22:51:59     1.46
  --- CHANGES   1996/08/02 20:39:09     1.47
  ***************
  *** 1,5 ****
  --- 1,11 ----
    Changes with Apache 1.2b1:
    
  +   *) Add setuid/gid execution via setuid wrapper
  +       Apache can now execute CGI scripts as the User/Group of the
  +       virtualhost, or as the owner of the UserDir through ~user.
  +       The wrapper program (suexec) is detected and configured at
  +       startup. [Randy Terbush, Jason Dour]
  + 
      *) Supplemental POSIX regex package included in source
          for those platforms that require/want it. We start needing
          POSIX/regex...
  ***************
  *** 16,22 ****
          changed #tmpXXXX to tmpXXXX in temp file template, for broken 
link/unlink
          changed Expire to Expires in cache_update()
          added appropriate #defines for Next compile
  !       added $Id: CHANGES,v 1.46 1996/07/29 22:51:59 jim Exp $ for RCS/CVS 
[Chuck Murcko]
    
      *) Fix ErrorDocument handling.  When ErrorDocument failed it used to 
         display filename instead of error message. [Paul Sutton]
  --- 22,28 ----
          changed #tmpXXXX to tmpXXXX in temp file template, for broken 
link/unlink
          changed Expire to Expires in cache_update()
          added appropriate #defines for Next compile
  !       added $Id: CHANGES,v 1.47 1996/08/02 20:39:09 randy Exp $ for RCS/CVS 
[Chuck Murcko]
    
      *) Fix ErrorDocument handling.  When ErrorDocument failed it used to 
         display filename instead of error message. [Paul Sutton]
  
  
  
  1.3       +1 -0      apache/src/http_conf_globals.h
  
  Index: http_conf_globals.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_conf_globals.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -C3 -r1.2 -r1.3
  *** http_conf_globals.h       1996/02/22 11:46:43     1.2
  --- http_conf_globals.h       1996/08/02 20:39:11     1.3
  ***************
  *** 67,72 ****
  --- 67,73 ----
    extern int daemons_min_free;
    extern int daemons_max_free;
    extern int daemons_limit;
  + extern int suexec_enabled;
    
    extern char *pid_fname;
    extern char *scoreboard_fname;
  
  
  
  1.28      +31 -8     apache/src/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_core.c,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -C3 -r1.27 -r1.28
  *** http_core.c       1996/07/29 18:09:13     1.27
  --- http_core.c       1996/08/02 20:39:13     1.28
  ***************
  *** 709,715 ****
    
    char *end_virthost_magic = "</Virtualhost> out of place";
    
  ! char *end_virtualhost_section (cmd_parms *cmd, void *dummy) {
        return end_virthost_magic;
    }
    
  --- 709,716 ----
    
    char *end_virthost_magic = "</Virtualhost> out of place";
    
  ! char *end_virtualhost_section (cmd_parms *cmd, void *dummy)
  ! {
        return end_virthost_magic;
    }
    
  ***************
  *** 738,743 ****
  --- 739,747 ----
        if (s->access_confname)
        process_resource_config (s, s->access_confname, p, ptemp);
        
  +     s->server_uid = user_id;
  +     s->server_gid = group_id;
  +     
        if (errmsg == end_virthost_magic) return NULL;
        return errmsg;
    }
  ***************
  *** 767,780 ****
        return NULL;
    }
    
  ! char *set_user (cmd_parms *cmd, void *dummy, char *arg) {
  !     user_name = pstrdup (cmd->pool, arg);
  !     user_id = uname2id (user_name);
        return NULL;
    }
    
  ! char *set_group (cmd_parms *cmd, void *dummy, char *arg) {
  !     group_id = gname2id(arg);
        return NULL;
    }
    
  --- 771,803 ----
        return NULL;
    }
    
  ! char *set_user (cmd_parms *cmd, void *dummy, char *arg)
  ! {
  !     uid_t uid;
  !     
  !     uid = uname2id (arg);
  !     
  !     if (!cmd->server->is_virtual) {
  !     user_name = pstrdup (cmd->pool, arg);
  !     user_id = uid;
  !     }
  !     
  !     cmd->server->server_uid = uid;
  ! 
        return NULL;
    }
    
  ! char *set_group (cmd_parms *cmd, void *dummy, char *arg)
  ! {
  !     gid_t gid;
  !     
  !     gid = gname2id(arg);
  ! 
  !     if (!cmd->server->is_virtual)
  !     group_id = gid;
  !     
  !     cmd->server->server_gid = gid;
  ! 
        return NULL;
    }
    
  ***************
  *** 1018,1025 ****
    { "ServerType", server_type, NULL, RSRC_CONF, TAKE1,"'inetd' or 
'standalone'"},
    { "Port", server_port, NULL, RSRC_CONF, TAKE1, "a TCP port number"},
    { "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, 
FLAG, NULL },
  ! { "User", set_user, NULL, RSRC_CONF, TAKE1, "a username"},
  ! { "Group", set_group, NULL, RSRC_CONF, TAKE1, "a group name"},
    { "ServerAdmin", set_server_string_slot,
      (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
      "The email address of the server administrator" },
  --- 1041,1048 ----
    { "ServerType", server_type, NULL, RSRC_CONF, TAKE1,"'inetd' or 
'standalone'"},
    { "Port", server_port, NULL, RSRC_CONF, TAKE1, "a TCP port number"},
    { "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, 
FLAG, NULL },
  ! { "User", set_user, NULL, RSRC_CONF, TAKE1, "effective user id for this 
server"},
  ! { "Group", set_group, NULL, RSRC_CONF, TAKE1, "effective group id for this 
server"},
    { "ServerAdmin", set_server_string_slot,
      (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
      "The email address of the server administrator" },
  
  
  
  1.57      +19 -0     apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -C3 -r1.56 -r1.57
  *** http_main.c       1996/07/28 00:03:15     1.56
  --- http_main.c       1996/08/02 20:39:14     1.57
  ***************
  *** 89,94 ****
  --- 89,95 ----
    #include "scoreboard.h"
    #include <setjmp.h>
    #include <assert.h>
  + #include <sys/stat.h>
    #ifdef HAVE_SHMGET
    #include <sys/types.h>
    #include <sys/ipc.h>
  ***************
  *** 132,137 ****
  --- 133,139 ----
    int daemons_max_free;
    int daemons_limit;
    time_t restart_time;
  + int suexec_enabled = 0;
    
    char server_root[MAX_STRING_LEN];
    char server_confname[MAX_STRING_LEN];
  ***************
  *** 1122,1127 ****
  --- 1124,1145 ----
      }
    }
    
  + /* check to see if we have the 'suexec' setuid wrapper installed */
  + int init_suexec ()
  + {
  +     struct stat wrapper;
  +     
  +     if ((stat(SUEXEC_BIN, &wrapper)) != 0)
  +       return (suexec_enabled);
  +     
  +     if ((wrapper.st_mode & S_ISUID) && wrapper.st_uid == 0) {
  +       suexec_enabled = 1;
  +       fprintf(stderr, "Configuring Apache for use with suexec wrapper.\n");
  +     }
  + 
  +     return (suexec_enabled);
  + }
  + 
    static int is_graceful;
    static int generation;
    
  ***************
  *** 1821,1826 ****
  --- 1839,1845 ----
        setup_prelinked_modules();
        
        server_conf = read_config (pconf, ptrans, server_confname);
  +     suexec_enabled = init_suexec();
        
        if(standalone) {
            clear_pool (pconf); /* standalone_main rereads... */
  
  
  
  1.42      +31 -25    apache/src/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/httpd.h,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -C3 -r1.41 -r1.42
  *** httpd.h   1996/07/29 02:32:33     1.41
  --- httpd.h   1996/08/02 20:39:15     1.42
  ***************
  *** 169,174 ****
  --- 169,177 ----
    #define SHELL_PATH "/bin/sh"
    #endif
    
  + /* The path to the suExec wrapper */
  + #define SUEXEC_BIN "/usr/local/etc/httpd/sbin/suexec"
  + 
    /* The default string lengths */
    #define MAX_STRING_LEN HUGE_STRING_LEN
    #define HUGE_STRING_LEN 8192
  ***************
  *** 470,515 ****
    
    struct server_rec {
    
  !   server_rec *next;
      
  !   /* Full locations of server config info */
      
  !   char *srm_confname;
  !   char *access_confname;
      
  !   /* Contact information */
      
  !   char *server_admin;
  !   char *server_hostname;
  !   short port;                    /* for redirects, etc. */
      
  !   /* Log files --- note that transfer log is now in the modules... */
      
  !   char *error_fname;
  !   FILE *error_log;
      
  !   /* Module-specific configuration for server, and defaults... */
    
  !   int is_virtual;               /* true if this is the virtual server */
  !   void *module_config;              /* Config vector containing pointers to
                                 * modules' per-server config structures.
                                 */
  !   void *lookup_defaults;    /* MIME type info, etc., before we start
                                 * checking per-directory info.
                                 */
  !   /* Transaction handling */
    
  !   struct in_addr host_addr; /* The bound address, for this server */
  !   short host_port;              /* The bound port, for this server */
  !   int timeout;                      /* Timeout, in seconds, before we give 
up */
  !   int keep_alive_timeout;   /* Seconds we'll wait for another request */
  !   int keep_alive;           /* Maximum requests per connection */
    
  !   char *path;                       /* Pathname for ServerPath */
  !   int pathlen;                      /* Length of path */
    
  !   char *names;                      /* Wildcarded names for HostAlias 
servers */
  !   char *virthost;           /* The name given in <VirtualHost> */
    };
    
    /* These are more like real hosts than virtual hosts */
  --- 473,521 ----
    
    struct server_rec {
    
  !     server_rec *next;
      
  !     /* Full locations of server config info */
      
  !     char *srm_confname;
  !     char *access_confname;
      
  !     /* Contact information */
      
  !     char *server_admin;
  !     char *server_hostname;
  !     short port;                    /* for redirects, etc. */
      
  !     /* Log files --- note that transfer log is now in the modules... */
      
  !     char *error_fname;
  !     FILE *error_log;
      
  !     /* Module-specific configuration for server, and defaults... */
    
  !     int is_virtual;             /* true if this is the virtual server */
  !     void *module_config;    /* Config vector containing pointers to
                                 * modules' per-server config structures.
                                 */
  !     void *lookup_defaults;  /* MIME type info, etc., before we start
                                 * checking per-directory info.
                                 */
  !     /* Transaction handling */
  ! 
  !     struct in_addr host_addr;       /* The bound address, for this server */
  !     short host_port;            /* The bound port, for this server */
  !     int timeout;            /* Timeout, in seconds, before we give up */
  !     int keep_alive_timeout; /* Seconds we'll wait for another request */
  !     int keep_alive;         /* Maximum requests per connection */
    
  !     char *path;                     /* Pathname for ServerPath */
  !     int pathlen;            /* Length of path */
    
  !     char *names;            /* Wildcarded names for HostAlias servers */
  !     char *virthost;         /* The name given in <VirtualHost> */
    
  !     uid_t server_uid;               /* effective user id when calling exec 
wrapper */
  !     gid_t server_gid;               /* effective group id when calling exec 
wrapper */
    };
    
    /* These are more like real hosts than virtual hosts */
  
  
  
  1.16      +51 -8     apache/src/util_script.c
  
  Index: util_script.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util_script.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -C3 -r1.15 -r1.16
  *** util_script.c     1996/07/27 04:24:43     1.15
  --- util_script.c     1996/08/02 20:39:16     1.16
  ***************
  *** 369,375 ****
  --- 369,379 ----
    
    void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
    {
  +     char *execuser;
        core_dir_config *conf;
  +     struct passwd *pw;
  +     struct group *gr;
  +     
    
        conf = (core_dir_config *)pcalloc(r->pool, sizeof(core_dir_config));
        
  ***************
  *** 439,453 ****
            execv(r->filename, create_argv(r->pool, argv0, r->args));
        }
    #else
  !     
  !     if (shellcmd) 
  !     execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
    
  !     else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
  !     execle(r->filename, argv0, NULL, env);
    
  !     else
  !     execve(r->filename, create_argv(r->pool, argv0, r->args), env);
  !     
    #endif
    }
  --- 443,496 ----
            execv(r->filename, create_argv(r->pool, argv0, r->args));
        }
    #else
  !     if ( suexec_enabled &&
  !      ((r->server->server_uid != user_id) ||
  !       (r->server->server_gid != group_id) ||
  !       (!strncmp("/~",r->uri,2))) ) {
    
  !         if (!strncmp("/~",r->uri,2)) {
  !             r->uri += 2;
  !             if ((pw = getpwnam (getword (r->pool, &r->uri, '/'))) == NULL) {
  !             log_unixerr("getpwnam", NULL, "invalid username", r->server);
  !             return;
  !         }
  !             r->uri -= 2;
  !             gr = getgrgid (pw->pw_gid);
  !             execuser = (char *) palloc (r->pool, (sizeof(pw->pw_name) + 1));
  !             execuser = pstrcat (r->pool, "~", pw->pw_name, NULL);
  !         }
  !     else {
  !         if ((pw = getpwuid (r->server->server_uid)) == NULL) {
  !             log_unixerr("getpwuid", NULL, "invalid userid", r->server);
  !             return;
  !         }
  !             if ((gr = getgrgid (r->server->server_gid)) == NULL) {
  !             log_unixerr("getgrgid", NULL, "invalid groupid", r->server);
  !             return;
  !         }
  !             execuser = (char *) palloc (r->pool, sizeof(pw->pw_name));
  !             execuser = pw->pw_name;
  !         }
  !   
  !     if (shellcmd)
  !         execle(SUEXEC_BIN, SUEXEC_BIN, execuser, gr->gr_name, argv0, NULL, 
env);
    
  !     else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
  !         execle(SUEXEC_BIN, SUEXEC_BIN, execuser, gr->gr_name, argv0, NULL, 
env);
  !   
  !     else
  !         execle(SUEXEC_BIN, SUEXEC_BIN, execuser, gr->gr_name,
  !                create_argv(r->pool, argv0, r->args), NULL, env);
  !     }
  !     else {
  !     if (shellcmd) 
  !         execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env);
  !     
  !     else if((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0))
  !         execle(r->filename, argv0, NULL, env);
  ! 
  !     else
  !         execve(r->filename, create_argv(r->pool, argv0, r->args), env);
  !     }
    #endif
    }
  
  
  

Reply via email to