Import Upstream version 1.8.5
[hcoop/debian/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 char *afs_defaultCell;
55 u_long afs_cacheExpiration;
56 u_long afs_tokenExpiration;
57 char *afs_weblogPath;
58 char *afs_accessLog;
59 u_long afs_debugLevel;
60 } afs_server_config_rec;
61
62
63 /* Data type for per directory configuration */
64 typedef struct {
65 char *afs_authtype;
66 char *afs_prompt;
67 char *afs_cell;
68 } afs_dir_config_rec;
69
70
71 static int initialized = 0;
72
73 static char defaultCell[64];
74 static u_long cacheExpiration;
75 int logAccessErrors = 0;
76 int logfd = -1;
77
78 static int afsAccessFile_flags = (O_WRONLY | O_APPEND | O_CREAT);
79 #ifdef __EMX__
80 /* OS/2 dosen't support users and groups */
81 static mode_t afsAccessFile_mode = (S_IREAD | S_IWRITE);
82 #else
83 static mode_t afsAccessFile_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
84 #endif
85
86 void
87 afs_init(server_rec * s, pool * p)
88 {
89 if (!initialized) {
90 char *weblogPath;
91 afs_server_config_rec *src =
92 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,
105 "AFS Module: SetAFSDEfaultCell <cellname> "
106 "is a required directive for module to work. Exiting\n");
107 exit(1);
108 }
109 tokenExpiration = src->afs_tokenExpiration;
110 cacheExpiration = src->afs_cacheExpiration;
111 afsDebugLevel = src->afs_debugLevel;
112
113 if ((src->afs_accessLog == NULL) || (src->afs_accessLog == "")) {
114 logAccessErrors = 0;
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,
120 "afs_module:Error opening afs access log file:%s\n"
121 "Error:%s,Exiting\n", strerror(errno), filename);
122 exit(-1);
123 }
124 logAccessErrors = 1;
125 }
126
127 if (cacheExpiration < 0) {
128 cacheExpiration = DEFAULT_CACHE_EXPIRATION;
129 }
130 if (tokenExpiration < 0) {
131 tokenExpiration = DEFAULT_TOKEN_EXPIRATION;
132 }
133
134 if (afsDebugLevel < 0) {
135 afsDebugLevel = DEFAULT_DEBUG_LEVEL;
136 }
137
138 if (cacheExpiration > tokenExpiration) {
139 fprintf(stderr,
140 "tokenExpiration:%d is less than cacheExpiration:%d\n",
141 tokenExpiration, cacheExpiration);
142 fprintf(stderr, "\n\n");
143 fprintf(stderr,
144 "Ensure that this does not happen, since you will "
145 "not be allowed access to files if the cached token has expired "
146 "because the token lifetime is less than the cache expiration "
147 "time. Restart the server after editing the config file\n");
148 exit(1);
149 }
150
151 if (!cacheExpiration && tokenExpiration) {
152 fprintf(stderr,
153 "cacheExpiration is set to infinity (0), but "
154 "tokenExpiration:%d is finite\n", tokenExpiration);
155 fprintf(stderr, "\n\n");
156 fprintf(stderr,
157 "Ensure that this does not happen, since you will "
158 "not be allowed access to files if the cached token has expired "
159 "because the token lifetime is less than the cache expiration "
160 "time (infinite). "
161 "Restart the server after editing the config file\n");
162 }
163 #ifdef SHUTDOWN_IF_AFS_FAILS
164 afs_plugin_init(tokenExpiration, server_root_relative(p, weblogPath),
165 server_root_relative(p, s->error_fname),
166 server_root_relative(p, pid_fname), defaultCell, NULL,
167 cacheExpiration, NULL, 1);
168 #else
169 afs_plugin_init(tokenExpiration, server_root_relative(p, weblogPath),
170 server_root_relative(p, s->error_fname),
171 server_root_relative(p, pid_fname), defaultCell, NULL,
172 cacheExpiration, NULL, 0);
173 #endif
174 }
175 }
176
177 static int
178 check_weblog(char *path)
179 {
180 struct stat fs;
181 int rc = stat(path, &fs);
182 if (rc)
183 return rc;
184
185 if (!((fs.st_mode & S_IXUSR) || (fs.st_mode & S_IXGRP)
186 || (fs.st_mode & S_IXOTH)))
187 return 2;
188 return 0;
189 }
190
191 /*
192 * per-server configuration creator
193 */
194 void *
195 create_afs_server_config(pool * p, server_rec * s)
196 {
197 afs_server_config_rec *scr =
198 (afs_server_config_rec *) pcalloc(p, sizeof(afs_server_config_rec));
199 scr->afs_cacheExpiration = 0;
200 scr->afs_tokenExpiration = 0;
201 scr->afs_debugLevel = 0;
202 return (void *)scr;
203 }
204
205 /*
206 * per-dir configuration record creator
207 */
208 void *
209 create_afs_dir_config(pool * p, char *dummy)
210 {
211 afs_dir_config_rec *new =
212 (afs_dir_config_rec *) pcalloc(p, sizeof(afs_dir_config_rec));
213 return (void *)new;
214 }
215
216 /*
217 * Handlers for server config lines - set afs default cell, weblog path, access log,
218 * token and cache expiration time to the server configuration. As well as per-dir
219 * configs like AFSAuthentication.
220 */
221 const char *
222 set_afscell(cmd_parms * cmd, void *dummy, char *arg)
223 {
224 void *sc = cmd->server->module_config;
225 afs_server_config_rec *sr = get_module_config(sc, &afs_module);
226
227 if ((arg == NULL) || (arg[0] == '\0'))
228 return "AFS Default cell is a required directive";
229
230 sr->afs_defaultCell = arg;
231 return NULL;
232 }
233
234 const char *
235 set_afsweblogpath(cmd_parms * cmd, void *dummy, char *arg)
236 {
237 void *sc = cmd->server->module_config;
238 afs_server_config_rec *sr = get_module_config(sc, &afs_module);
239 int rc = check_weblog(arg);
240 if (rc) {
241 switch (rc) {
242 case 1:
243 return
244 "Weblog Path should be the full path to the weblog_starter binary";
245 case 2:
246 return "weblog_starter not executable";
247 }
248 }
249 sr->afs_weblogPath = arg;
250 return NULL;
251 }
252
253 const char *
254 set_afsacceslog(cmd_parms * cmd, void *dummy, char *arg)
255 {
256 void *sc = cmd->server->module_config;
257 afs_server_config_rec *sr = get_module_config(sc, &afs_module);
258 sr->afs_accessLog = arg;
259 return NULL;
260 }
261
262 static const char *
263 set_afs_CacheExpiration(cmd_parms * cmd, void *dummy, char *expTime)
264 {
265 afs_server_config_rec *sr =
266 get_module_config(cmd->server->module_config, &afs_module);
267 sr->afs_cacheExpiration = atol(expTime);
268 return NULL;
269 }
270
271 static const char *
272 set_afs_TokenExpiration(cmd_parms * cmd, void *dummy, char *expTime)
273 {
274 afs_server_config_rec *sr =
275 get_module_config(cmd->server->module_config, &afs_module);
276 sr->afs_tokenExpiration = atol(expTime);
277 return NULL;
278 }
279
280 static const char *
281 set_afs_DebugLevel(cmd_parms * cmd, void *dummy, char *debugLevel)
282 {
283 afs_server_config_rec *sr = get_module_config(cmd->server->module_config,
284 &afs_module);
285 sr->afs_debugLevel = atol(debugLevel);
286 return NULL;
287 }
288
289 /* Commands this module needs to handle */
290 command_rec afs_cmds[] = {
291 {"SetAFSDefaultCell", set_afscell, NULL,
292 RSRC_CONF, TAKE1, "the AFS cell you want to access by default"}
293 ,
294
295 {"SetAFSCacheExpiration", set_afs_CacheExpiration, NULL, RSRC_CONF, TAKE1,
296 "time for tokens in the client cache to live"}
297 ,
298
299 {"SetAFSWeblogPath", set_afsweblogpath, NULL, RSRC_CONF, TAKE1,
300 "full or relative to ServerRoot path to the weblog_starter binary"}
301 ,
302
303 {"SetAFSTokenExpiration", set_afs_TokenExpiration, NULL, RSRC_CONF, TAKE1,
304 "time for tokens in the kernel cache to live"}
305 ,
306
307 {"SetAFSAccessLog", set_afsacceslog, NULL, RSRC_CONF, TAKE1,
308 "log afs access errors to this file"}
309 ,
310
311 {"SetAFSDebugLevel", set_afs_DebugLevel, NULL, RSRC_CONF, TAKE1,
312 "Set Verbosity level for logging stuff to the error log"}
313 ,
314
315 {"AFSLoginPrompt", set_string_slot,
316 (void *)XtOffsetOf(afs_dir_config_rec, afs_prompt), ACCESS_CONF, TAKE1,
317 "Prompt to show on Authenticating Window - similar to AuthName"},
318
319 {"AFSAuthType", set_string_slot,
320 (void *)XtOffsetOf(afs_dir_config_rec, afs_authtype), ACCESS_CONF, TAKE1,
321 "Authentication type for AFS"},
322
323 {"AFSDefaultCell", set_string_slot,
324 (void *)XtOffsetOf(afs_dir_config_rec, afs_cell), ACCESS_CONF, TAKE1,
325 "Default AFS cell for this location"},
326
327 {NULL}
328 };
329
330 char *
331 get_afsauthtype(request_rec * r)
332 {
333 afs_dir_config_rec *dr = (afs_dir_config_rec *)
334 get_module_config(r->per_dir_config, &afs_module);
335 if (!dr->afs_authtype) {
336 /* Try to unite CGI subprocess configuration info */
337 if (r->main) {
338 dr = (afs_dir_config_rec *)
339 get_module_config(r->main->per_dir_config, &afs_module);
340 }
341 }
342 return dr->afs_authtype;
343 }
344
345 char *
346 get_afs_authprompt(request_rec * r)
347 {
348 afs_dir_config_rec *dr =
349 (afs_dir_config_rec *) get_module_config(r->per_dir_config,
350 &afs_module);
351 if (!dr->afs_prompt) {
352 /* Try to unite CGI subprocess configuration info */
353 if (r->main) {
354 dr = (afs_dir_config_rec *)
355 get_module_config(r->main->per_dir_config, &afs_module);
356 }
357 }
358 return dr->afs_prompt;
359 }
360
361 static char *
362 get_afs_cell(request_rec * r)
363 {
364 afs_dir_config_rec *dr =
365 (afs_dir_config_rec *) get_module_config(r->per_dir_config,
366 &afs_module);
367 if (!dr->afs_cell) {
368 /* Try to unite CGI subprocess configuration info */
369 if (r->main) {
370 dr = (afs_dir_config_rec *)
371 get_module_config(r->main->per_dir_config, &afs_module);
372 }
373 }
374 return dr->afs_cell;
375 }
376
377 int
378 afs_auth(request_rec * r)
379 {
380 char *cell = get_afs_cell(r);
381 return afs_auth_internal(r, cell ? cell : defaultCell, cacheExpiration);
382 }
383
384
385
386 module afs_module = {
387 STANDARD_MODULE_STUFF,
388 afs_init,
389 create_afs_dir_config,
390 NULL,
391 create_afs_server_config,
392 NULL,
393 afs_cmds,
394 NULL,
395 afs_auth,
396 NULL,
397 NULL,
398 NULL,
399 NULL,
400 NULL,
401 NULL,
402 NULL,
403 };