source: server/common/oursrc/httpdmods/mod_authz_afsgroup.c @ 229

Last change on this file since 229 was 229, checked in by andersk, 18 years ago
Slay zombie pts processes.
File size: 4.7 KB
Line 
1/* mod_authz_afsgroup
2 * version 1.0, released 2006-01-04
3 * Anders Kaseorg <anders@kaseorg.com>
4 *
5 * This module does authorization based on AFS groups:
6 *   Require afsgroup system:administrators
7 *
8 * It currently works by parsing the output of `pts membership
9 * <group>`.
10 */
11
12#include "apr_strings.h"
13
14#include "ap_config.h"
15#include "httpd.h"
16#include "http_config.h"
17#include "http_core.h"
18#include "http_log.h"
19#include "http_protocol.h"
20#include "http_request.h"
21
22#include <unistd.h>
23#include <stdio.h>
24
25typedef struct {
26    int authoritative;
27} authz_afsgroup_config_rec;
28
29static void *create_authz_afsgroup_dir_config(apr_pool_t *p, char *d)
30{
31    authz_afsgroup_config_rec *conf = apr_palloc(p, sizeof(*conf));
32
33    conf->authoritative = 1;
34    return conf;
35}
36
37static const command_rec authz_afsgroup_cmds[] =
38{
39    AP_INIT_FLAG("AuthzAFSGroupAuthoritative", ap_set_flag_slot,
40                 (void *)APR_OFFSETOF(authz_afsgroup_config_rec, authoritative),
41                 OR_AUTHCFG,
42                 "Set to 'Off' to allow access control to be passed along to "
43                 "lower modules if the 'require afsgroup' statement is not "
44                 "met. (default: On)."),
45    {NULL}
46};
47
48module AP_MODULE_DECLARE_DATA authz_afsgroup_module;
49
50static int check_afsgroup_access(request_rec *r)
51{
52    authz_afsgroup_config_rec *conf = ap_get_module_config(r->per_dir_config,
53                                                           &authz_afsgroup_module);
54    char *user = r->user;
55    int m = r->method_number;
56    int required_afsgroup = 0;
57    register int x;
58    const char *t;
59    char *w;
60    const apr_array_header_t *reqs_arr = ap_requires(r);
61    require_line *reqs;
62
63    if (!reqs_arr) {
64        return DECLINED;
65    }
66    reqs = (require_line *)reqs_arr->elts;
67
68    for (x = 0; x < reqs_arr->nelts; x++) {
69
70        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
71            continue;
72        }
73
74        t = reqs[x].requirement;
75        w = ap_getword_white(r->pool, &t);
76        if (!strcasecmp(w, "afsgroup")) {
77            required_afsgroup = 1;
78            while (t[0]) {
79                int pfd[2];
80                pid_t cpid;
81                int status;
82                FILE *fp;
83                char *line = NULL;
84                char buf[256];
85                size_t len = 0;
86                ssize_t read;
87                int found = 0;
88                w = ap_getword_conf(r->pool, &t);
89                if (pipe(pfd) == -1) {
90                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
91                                  "pipe() failed!");
92                    return HTTP_INTERNAL_SERVER_ERROR;
93                }
94                cpid = fork();
95                if (cpid == -1) {
96                    close(pfd[0]);
97                    close(pfd[1]);
98                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
99                                  "fork() failed!");
100                    return HTTP_INTERNAL_SERVER_ERROR;
101                }
102                if (cpid == 0) {
103                    close(pfd[0]);
104                    dup2(pfd[1], STDOUT_FILENO);
105                    execve("/usr/bin/pts",
106                           (char *const[]) {
107                               "pts", "membership", "-nameorid", w, NULL
108                           },
109                           NULL);
110                    _exit(1);
111                }
112                close(pfd[1]);
113                fp = fdopen(pfd[0], "r");
114                if (fp == NULL) {
115                    close(pfd[0]);
116                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
117                                  "fdopen() failed!");
118                    return HTTP_INTERNAL_SERVER_ERROR;
119                }
120                if (snprintf(buf, sizeof(buf), "  %s\n", user) >= sizeof(buf)) {
121                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
122                                  "access to %s failed, reason: username '%s' "
123                                  "is too long!",
124                                  r->uri, user);
125                    continue;
126                }
127                while ((read = getline(&line, &len, fp)) != -1) {
128                    if (strcmp(line, buf) == 0)
129                        found = 1;
130                }
131                if (line)
132                    free(line);
133                fclose(fp);
134                if (waitpid(cpid, &status, 0) == -1) {
135                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
136                                  "waitpid() failed!");
137                    return HTTP_INTERNAL_SERVER_ERROR;
138                }
139                if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
140                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
141                                  "`pts membership -nameorid %s` failed!",
142                                  w);
143                    return HTTP_INTERNAL_SERVER_ERROR;
144                }
145                if (found)
146                    return OK;
147            }
148        }
149    }
150
151    if (!required_afsgroup) {
152        return DECLINED;
153    }
154
155    if (!conf->authoritative) {
156        return DECLINED;
157    }
158
159    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
160                  "access to %s failed, reason: user '%s' does not meet "
161                  "'require'ments for afsgroup to be allowed access",
162                  r->uri, user);
163
164    ap_note_auth_failure(r);
165    return HTTP_FORBIDDEN;
166}
167
168static void register_hooks(apr_pool_t *p)
169{
170    ap_hook_auth_checker(check_afsgroup_access, NULL, NULL, APR_HOOK_MIDDLE);
171}
172
173module AP_MODULE_DECLARE_DATA authz_afsgroup_module =
174{
175    STANDARD20_MODULE_STUFF,
176    create_authz_afsgroup_dir_config, /* dir config creater */
177    NULL,                             /* dir merger --- default is to override */
178    NULL,                             /* server config */
179    NULL,                             /* merge server config */
180    authz_afsgroup_cmds,              /* command apr_table_t */
181    register_hooks                    /* register hooks */
182};
Note: See TracBrowser for help on using the repository browser.