Standardize License information
[openafs.git] / src / afsweb / apache_afs_module.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * afs_module  Version 1.3     < for Apache Server version 1.2.6 and 1.3.1 >
12  * 
13  * Add to Configuration file (before any of the Authentication modules)
14  * Module afs_module    afs_module.o
15  * 
16  * Add to server configuration file:
17  * SetAFSDefaultCell <cell name>
18  * SetAFSCacheExpiration <seconds for AFS client cache expiration>
19  * SetAFSTokenExpiration <seconds for AFS token expiration>
20  * SetAFSWeblogPath <path (full or relative to ServerRoot to the weblog_starter binary>
21  * SetAFSDebugLevel <positive integer for verbosity level of error logs>
22  * Per directory configuration for locations that AFS access is desired may
23  * be specified as follows Eg.
24  * <Location /afs>
25  * ## Optionally set default cell for this location AFSDefaultCell <cell name>
26  * AFSAuthType AFS
27  * AFSLoginPrompt AFS Login for <%c/%d>
28  * </Location>
29  */
30
31 #include "httpd.h"
32 #include "http_config.h"
33 #include "http_core.h"
34 #include "http_conf_globals.h"
35
36
37 /* 
38  * default parameters - if none are specified in the config file
39  * these are used
40  */
41 #define DEFAULT_WEBLOG_PATH                   "./weblog_starter"
42 #define DEFAULT_CACHE_EXPIRATION              300            /* 5 minutes */
43 #define DEFAULT_TOKEN_EXPIRATION              600            /* 10 minutes */
44 #define DEFAULT_DEBUG_LEVEL                   0
45 #define null ((void*)0) 
46
47 extern u_long afsDebugLevel;
48
49 /* forward declaration, see defination at end of file */
50 module afs_module;
51
52 /* Data type for server configuration */
53 typedef struct
54 {
55   char *afs_defaultCell;
56   u_long afs_cacheExpiration;
57   u_long afs_tokenExpiration;
58   char *afs_weblogPath;
59   char *afs_accessLog;
60   u_long afs_debugLevel;
61 } afs_server_config_rec;
62
63
64 /* Data type for per directory configuration */
65 typedef struct
66 {
67   char *afs_authtype;
68   char *afs_prompt;
69   char *afs_cell;
70 } afs_dir_config_rec;
71
72
73 static int initialized = 0;
74
75 static char defaultCell[64];
76 static u_long cacheExpiration;
77 int logAccessErrors = 0;
78 int logfd = -1;
79
80 static int afsAccessFile_flags = ( O_WRONLY | O_APPEND | O_CREAT );
81 #ifdef __EMX__
82 /* OS/2 dosen't support users and groups */
83 static mode_t afsAccessFile_mode = ( S_IREAD | S_IWRITE );
84 #else
85 static mode_t afsAccessFile_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
86 #endif
87
88 void afs_init(server_rec *s, pool *p)
89 {
90   if (!initialized) {
91     char *weblogPath;
92     afs_server_config_rec *src = get_module_config(s->module_config, &afs_module);
93     int tokenExpiration = src->afs_tokenExpiration;
94
95     initialized = 1;
96     if (src->afs_weblogPath)
97       weblogPath = pstrdup(p, src->afs_weblogPath);
98     else 
99       weblogPath = pstrdup(p, DEFAULT_WEBLOG_PATH);
100
101     if (src->afs_defaultCell)
102       strcpy(defaultCell,src->afs_defaultCell);
103     else {
104       fprintf(stderr, "AFS Module: SetAFSDEfaultCell <cellname> " 
105               "is a required directive for module to work. Exiting\n");
106       exit(1);
107     }
108     tokenExpiration = src->afs_tokenExpiration;
109     cacheExpiration = src->afs_cacheExpiration;
110     afsDebugLevel = src->afs_debugLevel;
111
112     if ((src->afs_accessLog == NULL) || (src->afs_accessLog == "")) {
113       logAccessErrors = 0;
114     }
115     else {
116       char *filename = server_root_relative(p, src->afs_accessLog);
117       logfd = open(filename,afsAccessFile_flags, afsAccessFile_mode);
118       if (logfd < 0) {
119         fprintf(stderr, "afs_module:Error opening afs access log file:%s\n"
120                 "Error:%s,Exiting\n",strerror(errno),filename);
121         exit(-1);
122       }
123       logAccessErrors = 1;
124     }
125
126     if (cacheExpiration < 0) {
127       cacheExpiration = DEFAULT_CACHE_EXPIRATION;
128     }
129     if (tokenExpiration < 0) {
130       tokenExpiration = DEFAULT_TOKEN_EXPIRATION;
131     }
132     
133     if (afsDebugLevel < 0) {
134       afsDebugLevel = DEFAULT_DEBUG_LEVEL;
135     }
136
137     if (cacheExpiration > tokenExpiration) {
138       fprintf(stderr, "tokenExpiration:%d is less than cacheExpiration:%d\n",
139               tokenExpiration, cacheExpiration);
140       fprintf(stderr, "\n\n");
141       fprintf(stderr, "Ensure that this does not happen, since you will "
142               "not be allowed access to files if the cached token has expired "
143               "because the token lifetime is less than the cache expiration "
144               "time. Restart the server after editing the config file\n");
145       exit(1);
146     }
147     
148     if (!cacheExpiration && tokenExpiration) {
149       fprintf(stderr, "cacheExpiration is set to infinity (0), but "
150               "tokenExpiration:%d is finite\n",tokenExpiration);
151       fprintf(stderr, "\n\n");
152       fprintf(stderr, "Ensure that this does not happen, since you will "
153               "not be allowed access to files if the cached token has expired "
154               "because the token lifetime is less than the cache expiration "
155               "time (infinite). "
156               "Restart the server after editing the config file\n");
157     }      
158 #ifdef SHUTDOWN_IF_AFS_FAILS
159     afs_plugin_init(tokenExpiration, 
160                     server_root_relative(p, weblogPath),
161                     server_root_relative(p, s->error_fname),
162                     server_root_relative(p, pid_fname),
163                     defaultCell, NULL, cacheExpiration, NULL,
164                     1);
165 #else
166     afs_plugin_init(tokenExpiration, 
167                     server_root_relative(p, weblogPath),
168                     server_root_relative(p, s->error_fname),    
169                     server_root_relative(p, pid_fname),
170                     defaultCell, NULL, cacheExpiration, NULL,
171                     0);
172 #endif
173   }
174 }
175
176 static int check_weblog(char *path)
177 {
178   struct stat fs;
179   int rc = stat(path, &fs);
180   if (rc)
181     return rc;
182
183   if (!((fs.st_mode & S_IXUSR) || (fs.st_mode & S_IXGRP) || (fs.st_mode & S_IXOTH))) 
184     return 2;
185   return 0;
186 }
187
188 /* 
189  * per-server configuration creator 
190  */
191 void *create_afs_server_config (pool *p, server_rec *s)
192 {
193   afs_server_config_rec *scr =  
194     (afs_server_config_rec *) pcalloc(p, sizeof(afs_server_config_rec));
195   scr->afs_cacheExpiration = 0;
196   scr->afs_tokenExpiration = 0;
197   scr->afs_debugLevel = 0;
198   return (void *)scr;
199 }
200
201 /*
202  * per-dir configuration record creator 
203  */
204 void *create_afs_dir_config (pool *p, char *dummy)
205 {
206   afs_dir_config_rec *new =
207     (afs_dir_config_rec *)pcalloc(p,sizeof(afs_dir_config_rec));
208   return (void *)new;
209 }
210
211 /*
212  * Handlers for server config lines - set afs default cell, weblog path, access log,
213  * token and cache expiration time to the server configuration. As well as per-dir 
214  * configs like AFSAuthentication.
215  */
216 const char *set_afscell(cmd_parms *cmd, void *dummy, char *arg)
217 {
218    void *sc = cmd->server->module_config;
219    afs_server_config_rec *sr = get_module_config(sc, &afs_module);
220  
221    if ((arg == NULL)||(arg[0] == '\0')) 
222      return "AFS Default cell is a required directive";
223
224     sr->afs_defaultCell = arg;
225     return NULL;
226 }
227
228 const char *set_afsweblogpath(cmd_parms *cmd, void *dummy, char *arg)
229 {
230   void *sc = cmd->server->module_config;
231   afs_server_config_rec *sr = get_module_config(sc, &afs_module);
232   int rc = check_weblog(arg);
233   if (rc) {
234     switch (rc) {
235     case 1:
236       return "Weblog Path should be the full path to the weblog_starter binary";
237     case 2:
238       return "weblog_starter not executable";
239     }
240    }
241   sr->afs_weblogPath = arg;
242   return NULL;
243 }
244
245 const char *set_afsacceslog(cmd_parms *cmd, void *dummy, char *arg)
246 {
247   void *sc = cmd->server->module_config;
248   afs_server_config_rec *sr = get_module_config(sc,&afs_module);
249   sr->afs_accessLog = arg;
250   return NULL;
251 }
252
253 static const char *set_afs_CacheExpiration(cmd_parms *cmd, void *dummy, char *expTime)
254 {
255   afs_server_config_rec *sr =
256     get_module_config(cmd->server->module_config, &afs_module);
257   sr->afs_cacheExpiration = atol(expTime);
258   return NULL;
259 }
260
261 static const char *set_afs_TokenExpiration(cmd_parms *cmd, void *dummy, char *expTime)
262 {
263   afs_server_config_rec *sr =
264     get_module_config(cmd->server->module_config, &afs_module);
265   sr->afs_tokenExpiration = atol(expTime);
266   return NULL;
267 }
268
269 static const char *set_afs_DebugLevel(cmd_parms *cmd, void *dummy, char *debugLevel) 
270 {
271   afs_server_config_rec *sr = get_module_config(cmd->server->module_config,
272                                                 &afs_module);
273   sr->afs_debugLevel = atol(debugLevel);
274   return NULL;
275 }
276
277 /* Commands this module needs to handle */
278 command_rec afs_cmds[] = {
279   { "SetAFSDefaultCell", set_afscell, NULL,
280       RSRC_CONF, TAKE1,"the AFS cell you want to access by default" },
281   
282   { "SetAFSCacheExpiration", set_afs_CacheExpiration, NULL, RSRC_CONF, TAKE1,
283     "time for tokens in the client cache to live" },
284
285   { "SetAFSWeblogPath",set_afsweblogpath, NULL, RSRC_CONF, TAKE1,
286     "full or relative to ServerRoot path to the weblog_starter binary" },  
287   
288   { "SetAFSTokenExpiration", set_afs_TokenExpiration, NULL, RSRC_CONF, TAKE1,
289     "time for tokens in the kernel cache to live" },
290   
291   { "SetAFSAccessLog", set_afsacceslog, NULL, RSRC_CONF, TAKE1,
292     "log afs access errors to this file" },
293
294   { "SetAFSDebugLevel", set_afs_DebugLevel, NULL, RSRC_CONF, TAKE1,
295     "Set Verbosity level for logging stuff to the error log" },
296   
297   { "AFSLoginPrompt", set_string_slot, 
298     (void *)XtOffsetOf(afs_dir_config_rec, afs_prompt), ACCESS_CONF, TAKE1,
299     "Prompt to show on Authenticating Window - similar to AuthName"},
300   
301   { "AFSAuthType", set_string_slot, 
302     (void*)XtOffsetOf(afs_dir_config_rec, afs_authtype), ACCESS_CONF, TAKE1, 
303     "Authentication type for AFS" },
304   
305   { "AFSDefaultCell", set_string_slot, 
306     (void*)XtOffsetOf(afs_dir_config_rec, afs_cell), ACCESS_CONF, TAKE1, 
307     "Default AFS cell for this location" },
308   
309   { NULL }
310 };
311
312 char *get_afsauthtype(request_rec *r)
313 {
314   afs_dir_config_rec *dr = (afs_dir_config_rec *)
315     get_module_config(r->per_dir_config, &afs_module);
316   if (!dr->afs_authtype) {
317       /* Try to unite CGI subprocess configuration info */
318       if (r->main) {
319           dr = (afs_dir_config_rec *)
320               get_module_config(r->main->per_dir_config, &afs_module);
321       }
322   }
323   return dr->afs_authtype;
324 }
325
326 char *get_afs_authprompt(request_rec *r)
327 {
328   afs_dir_config_rec *dr =
329     (afs_dir_config_rec *)get_module_config(r->per_dir_config, &afs_module);
330   if (!dr->afs_prompt) {
331       /* Try to unite CGI subprocess configuration info */
332       if (r->main) {
333           dr = (afs_dir_config_rec *)
334               get_module_config(r->main->per_dir_config, &afs_module);
335       }
336   }
337   return dr->afs_prompt;
338 }
339
340 static char *get_afs_cell(request_rec *r)
341 {
342   afs_dir_config_rec *dr =
343    (afs_dir_config_rec *)get_module_config(r->per_dir_config, &afs_module);
344   if (!dr->afs_cell) {
345       /* Try to unite CGI subprocess configuration info */
346       if (r->main) {
347           dr = (afs_dir_config_rec *)
348               get_module_config(r->main->per_dir_config, &afs_module);
349       }
350   }
351   return dr->afs_cell; 
352 }
353
354 int afs_auth(request_rec *r)
355 {
356   char *cell = get_afs_cell(r);
357   return afs_auth_internal(r, cell ? cell : defaultCell, cacheExpiration);
358 }
359
360
361
362 module afs_module =
363 {
364    STANDARD_MODULE_STUFF,
365    afs_init,                    
366    create_afs_dir_config,       
367    NULL,
368    create_afs_server_config,    
369    NULL,                        
370    afs_cmds,                    
371    NULL,                        
372    afs_auth,                    
373    NULL,                        
374    NULL,                        
375    NULL,                        
376    NULL,                        
377    NULL,                        
378    NULL,                        
379    NULL,                        
380 };