source: trunk/server/common/oursrc/httpdmods/mod_authz_afsgroup.c

Last change on this file was 2591, checked in by achernya, 8 years ago
Reintegrate fc20-dev into trunk
File size: 4.8 KB
Line 
1/* mod_authz_afsgroup
2 * version 1.1, released 2007-03-13
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 "ap_provider.h"
16#include "httpd.h"
17#include "http_config.h"
18#include "http_core.h"
19#include "http_log.h"
20#include "http_protocol.h"
21#include "http_request.h"
22
23#include "mod_auth.h"
24
25#include <unistd.h>
26#include <stdio.h>
27
28typedef struct {
29    int authoritative;
30} authz_afsgroup_config_rec;
31
32static void *create_authz_afsgroup_dir_config(apr_pool_t *p, char *d)
33{
34    authz_afsgroup_config_rec *conf = apr_palloc(p, sizeof(*conf));
35
36    conf->authoritative = 1;
37    return conf;
38}
39
40static const command_rec authz_afsgroup_cmds[] =
41{
42    AP_INIT_FLAG("AuthzAFSGroupAuthoritative", ap_set_flag_slot,
43                 (void *)APR_OFFSETOF(authz_afsgroup_config_rec, authoritative),
44                 OR_AUTHCFG,
45                 "Set to 'Off' to allow access control to be passed along to "
46                 "lower modules if the 'require afsgroup' statement is not "
47                 "met. (default: On)."),
48    {NULL}
49};
50
51module AP_MODULE_DECLARE_DATA authz_afsgroup_module;
52
53static authz_status is_user_in_afsgroup(request_rec *r, char* user, char* afsgroup)
54{
55    int pfd[2];
56    pid_t cpid;
57    int status;
58    FILE *fp;
59    char *line = NULL;
60    char buf[256];
61    size_t len = 0;
62    ssize_t read;
63    int found = 0;
64    if (pipe(pfd) == -1) {
65        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
66                      "pipe() failed!");
67        return AUTHZ_GENERAL_ERROR;
68    }
69    cpid = fork();
70    if (cpid == -1) {
71        close(pfd[0]);
72        close(pfd[1]);
73        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
74                      "fork() failed!");
75        return AUTHZ_GENERAL_ERROR;
76    }
77    if (cpid == 0) {
78        close(pfd[0]);
79        dup2(pfd[1], STDOUT_FILENO);
80        execve("/usr/bin/pts",
81               (char *const[])
82               { "pts", "membership", "-nameorid", afsgroup, NULL },
83               NULL);
84        _exit(1);
85    }
86    close(pfd[1]);
87    fp = fdopen(pfd[0], "r");
88    if (fp == NULL) {
89        close(pfd[0]);
90        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
91                      "fdopen() failed!");
92        return AUTHZ_GENERAL_ERROR;
93    }
94    if (snprintf(buf, sizeof(buf), "  %s\n", user) >= sizeof(buf)) {
95        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
96                      "access to %s failed, reason: username '%s' "
97                      "is too long!",
98                      r->uri, user);
99        return AUTHZ_DENIED;
100    }
101    while ((read = getline(&line, &len, fp)) != -1) {
102        if (strcmp(line, buf) == 0)
103            found = 1;
104    }
105    if (line)
106        free(line);
107    fclose(fp);
108    if (waitpid(cpid, &status, 0) == -1) {
109        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
110                      "waitpid() failed!");
111        return AUTHZ_GENERAL_ERROR;
112    }
113    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
114        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
115                      "`pts membership -nameorid %s` failed!",
116                      afsgroup);
117        return AUTHZ_GENERAL_ERROR;
118    }
119    if (found)
120        return AUTHZ_GRANTED;
121
122    return AUTHZ_DENIED;
123}
124
125static authz_status check_afsgroup_access(request_rec *r,
126                                 const char *require_line,
127                                 const void *parsed_require_line)
128{
129    authz_afsgroup_config_rec *conf = ap_get_module_config(r->per_dir_config,
130                                                           &authz_afsgroup_module);
131    const char *t;
132    char *w;
133    authz_status pergroup;
134
135    if (!r->user) {
136        return AUTHZ_DENIED_NO_USER;
137    }
138
139    t = require_line;
140    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
141        if ((pergroup = is_user_in_afsgroup(r, r->user, w)) != AUTHZ_DENIED) {
142            // If we got some return value other than AUTHZ_DENIED, it
143            // means we either got GRANTED, or some sort of error, and
144            // we need to bubble that up.
145            return pergroup;
146        }
147    }
148
149    if (!conf->authoritative) {
150        return AUTHZ_NEUTRAL;
151    }
152
153    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
154                  "access to %s failed, reason: user '%s' does not meet "
155                  "'require'ments for afsgroup to be allowed access",
156                  r->uri, r->user);
157
158    return AUTHZ_DENIED;
159}
160
161static const authz_provider authz_afsgroup_provider =
162{
163    &check_afsgroup_access,
164    NULL,
165};
166
167static void register_hooks(apr_pool_t *p)
168{
169    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "afsgroup",
170                              AUTHZ_PROVIDER_VERSION,
171                              &authz_afsgroup_provider, AP_AUTH_INTERNAL_PER_CONF);
172
173}
174
175module AP_MODULE_DECLARE_DATA authz_afsgroup_module =
176{
177    STANDARD20_MODULE_STUFF,
178    create_authz_afsgroup_dir_config, /* dir config creater */
179    NULL,                             /* dir merger --- default is to override */
180    NULL,                             /* server config */
181    NULL,                             /* merge server config */
182    authz_afsgroup_cmds,              /* command apr_table_t */
183    register_hooks                    /* register hooks */
184};
Note: See TracBrowser for help on using the repository browser.