source: branches/fc19-dev/server/common/oursrc/httpdmods/mod_authz_afsgroup.c @ 2435

Last change on this file since 2435 was 2435, checked in by achernya, 9 years ago
Port httpdmods to httpd 2.4 mod_original_dst has very few changes; the mpm.h header is now missing, so hardcode the accept function in the now-nonexistant #define. If a better way to do this is found, this hard-coding should be replaced, but from inspecing the 2.4.4 source, this appears to be the best way. mod_authz_afsgroup has more extensive changes, due to the differences in how Apache 2.4 handles authorization. In theory, this should work the same way as before, and reduces the amount of code, as Apache will no longer force us to parse lines that are not relevant to us.
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.