Release a new version of the Apache module, with the context support.
[itkacl] / libapache2-mod-authz-itkacl-0.7 / mod_authz_itkacl.c
1 /*
2  * ITKACL module, (C) 2004-2022 Steinar H. Gunderson
3  */
4
5 #define MODAUTHITKACL_VERSION "0.7"
6
7 #include "apr_strings.h"
8
9 #include "ap_config.h"
10 #include "httpd.h"
11 #include "http_config.h"
12 #include "http_core.h"
13 #include "http_log.h"
14 #include "http_protocol.h"
15 #include "http_request.h"
16 #include "mod_auth.h"
17 #include "itkacl.h"
18
19 module AP_MODULE_DECLARE_DATA authz_itkacl_module;
20 static struct itkacl_ctx *ctx = NULL;
21
22 static int handle_require(request_rec *r, const char *username, const char *acl_path)
23 {
24         char errmsg[1024];
25         int ret;
26
27         ret = itkacl_check_with_ctx(ctx, acl_path, username, errmsg, 1024);
28         if (ret == 0) {
29                 return AUTHZ_GRANTED;
30         }
31
32         if (ret == -1) {
33                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
34                         "error during itkacl check for %s on %s: %s",
35                         username, acl_path, errmsg);
36         }
37
38         return AUTHZ_DENIED;
39 }
40
41 static authz_status authz_itkacl_authorize_user(request_rec *r, const char *require_line, const void *parsed_require_line)
42 {
43         char *username, *ptr;
44         const char *t, *acl_path;
45
46         if (r->user == NULL) {
47                 return AUTHZ_DENIED_NO_USER;
48         }
49
50         /* strip the domain part (FIXME: use the alias module instead?) */
51         username = apr_pstrdup(r->pool, r->user);
52         ptr = strchr(username, '@');
53         if (ptr != NULL)
54                 ptr[0] = 0;
55
56         t = require_line;
57         acl_path = ap_getword_conf(r->pool, &t);
58         if (acl_path == NULL || strcmp(acl_path, "") == 0) {
59                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "'require itkacl' requires an argument");
60                 return AUTHZ_DENIED;
61         }
62
63         if (strcasecmp(acl_path, "anyof") == 0) {
64                 int num_seen = 0, ret;
65                 while ((acl_path = ap_getword_conf(r->pool, &t)) != NULL &&
66                        strcmp(acl_path, "") != 0) {
67                         ret = handle_require(r, username, acl_path);
68                         if (ret == AUTHZ_GRANTED) {
69                                 return ret;
70                         }
71                         ++num_seen;
72                 }
73                 if (num_seen == 0) {
74                         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
75                                 "Missing arguments after 'Require itkacl anyof'");
76                         return AUTHZ_DENIED;
77                 } else if (ret == HTTP_UNAUTHORIZED) {
78                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
79                                 "%s failed itkacl check for (multiple paths)",
80                                 username);
81                         return AUTHZ_DENIED;
82                 }
83                 return ret;
84         } else {
85                 /* check that there are no more arguments */
86                 const char *w = ap_getword_conf(r->pool, &t);
87                 if (w != NULL && strcmp(w, "") != 0) {
88                         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
89                                 "Excess arguments ('%s') after Require itkacl %s; "
90                                 "did you mean 'Require itkacl anyof ...'?",
91                                 w, acl_path);
92                         return AUTHZ_DENIED;
93                 }
94
95                 int ret = handle_require(r, username, acl_path);
96                 if (ret == AUTHZ_DENIED) {
97                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
98                             "%s failed itkacl check for %s",
99                             username, acl_path);
100                         return AUTHZ_DENIED;
101                 }
102                 return ret;
103         }
104 }
105
106 static int authz_itkacl_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
107 {
108         ap_add_version_component(p, "mod_auth_itkacl/" MODAUTHITKACL_VERSION);
109         if (ctx != NULL) {
110                 itkacl_free_ctx(ctx);
111         }
112         {
113                 char errmsg[1024];
114                 ctx = itkacl_create_ctx(errmsg, sizeof(errmsg));
115                 if (ctx == NULL) {
116                         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Error while initializing libitkacl: %s", errmsg);
117                         return HTTP_INTERNAL_SERVER_ERROR;
118                 }
119         }
120         return OK;
121 }
122
123 static const authz_provider authz_itkacl_provider =
124 {
125         &authz_itkacl_authorize_user,
126         NULL,
127 };
128
129 void authz_itkacl_register_hooks(apr_pool_t *p)
130 {
131         ap_hook_post_config(authz_itkacl_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
132         ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "itkacl", AUTHZ_PROVIDER_VERSION, &authz_itkacl_provider, AP_AUTH_INTERNAL_PER_CONF);
133 }
134
135 module AP_MODULE_DECLARE_DATA authz_itkacl_module =
136 {
137         STANDARD20_MODULE_STUFF,
138         NULL,
139         NULL,
140         NULL,
141         NULL,
142         NULL,
143         authz_itkacl_register_hooks
144 };