chiark / gitweb /
a71bdb2691e861894bdf887f2d6e14a562687c23
[modbot-mtm.git] / webstump / src / wrapper.c
1 /*
2  * WebSTUMP wrapper. You have to compile this program using "make" and
3  * make sure that it is installed under ../bin. It should be set up as 
4  * setuid your user id. Directory referred to by webstump_home should
5  * exist and belong to the effective user id or the program will refuse
6  * to run.
7  */
8
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14
15 const char * webstump_home = WEBSTUMP_HOME;
16
17 const char * script_name = "scripts/webstump.pl";
18
19 const char *safe_env[] = {
20         "SERVER_SOFTWARE",
21         "SERVER_NAME",
22         "GATEWAY_INTERFACE",
23         "SERVER_PROTOCOL",
24         "SERVER_PORT",
25         "REQUEST_METHOD",
26         "HTTP_ACCEPT",
27         "PATH_INFO",
28         "PATH_TRANSLATED",
29         "SCRIPT_NAME",
30         "QUERY_STRING",
31         "REMOTE_HOST",
32         "REMOTE_ADDR",
33         "REMOTE_USER",
34         "AUTH_TYPE",
35         "CONTENT_TYPE",
36         "CONTENT_LENGTH",
37         NULL
38 };
39
40 void cgi_error( const char * buf );
41
42 /* Wrapper code. Argc and argv are ignored, except fot the list of 
43  * predefined variables.
44  */
45
46 int main( int argc, char * argv[] ) /* argv is ignored */
47 {
48   char * new_env[ 1000 ];       /* new environment */
49   char * new_argv[] = { NULL }; /* no arguments    */
50   char script_file_name[ 1024 ];
51   char buf[1024];
52   int i, new_env_i;
53   struct stat stat_buf;
54
55   for( i = 0, new_env_i = 0; safe_env[i] != NULL; i++ )
56   {
57     char * var;
58     if( (var = getenv( safe_env[i] )) != NULL ) {
59       char * new_var = malloc( strlen( safe_env[i] ) + 1 + strlen( var ) + 1 );
60       if( new_var != NULL )
61         {
62           strcpy( new_var, safe_env[i] );
63           strcat( new_var, "=" );
64           strcat( new_var, var );
65           new_env[ new_env_i++ ] = new_var;
66         }
67     }
68   }
69
70   new_env[new_env_i] = NULL;
71
72   /* check existence and ownership of the perl script */
73
74   strcpy( script_file_name, webstump_home );
75   strcat( script_file_name, "/" );
76   strcat( script_file_name, script_name );
77
78   if( stat( script_file_name, & stat_buf ) != 0 )
79     {
80       sprintf( buf, "Could not access file %s to check permissions.",
81                script_file_name );
82       cgi_error( buf );
83       exit( 0 );
84     }
85
86   if( stat_buf.st_uid != geteuid() )
87     {
88       sprintf( buf, "Security violation: file %s \n"
89                     "belongs to a different user than my effective user id.",
90                script_file_name );
91       cgi_error( buf );
92       exit( 0 );
93     }
94
95   if( stat_buf.st_mode & (0 | 02) ) /* group or world writable */
96     {
97 printf( "File mode = %o, compared to %o\n", stat_buf.st_mode, (020 | 02) );
98       sprintf( buf, "Security violation: file %s \n"
99                     "is group or world writable.",
100                script_file_name );
101       cgi_error( buf );
102       exit( 0 );
103     }
104
105   execve( script_file_name, new_argv, new_env );
106
107   /* We can only be here if it could not be executed */
108
109   sprintf( buf, "Error: could not execute file %s", script_file_name );
110   cgi_error( buf );
111 }
112
113
114 void cgi_error( const char * buf )
115 {
116   printf( 
117 "Content-Type: text/html\n\n"
118 "<TITLE>WebSTUMP Error</TITLE>\n"
119 "<H1>WebSTUMP Error</H1>\n"
120 "%s\n\n", 
121         buf );
122 }