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