Commit | Line | Data |
---|---|---|
805e021f CE |
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 | }; |