Line data Source code
1 : /*
2 : SSSD
3 :
4 : Simple access control
5 :
6 : Copyright (C) Sumit Bose <sbose@redhat.com> 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <security/pam_modules.h>
23 :
24 : #include "providers/simple/simple_access.h"
25 : #include "util/sss_utf8.h"
26 : #include "providers/dp_backend.h"
27 : #include "db/sysdb.h"
28 :
29 : #define CONFDB_SIMPLE_ALLOW_USERS "simple_allow_users"
30 : #define CONFDB_SIMPLE_DENY_USERS "simple_deny_users"
31 :
32 : #define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups"
33 : #define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups"
34 :
35 : #define TIMEOUT_OF_REFRESH_FILTER_LISTS 5
36 :
37 : static void simple_access_check(struct tevent_req *req);
38 : static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
39 : struct be_ctx *be_ctx,
40 : char **list,
41 : char ***_out);
42 :
43 1 : static int simple_access_obtain_filter_lists(struct simple_ctx *ctx)
44 : {
45 1 : struct be_ctx *bectx = ctx->be_ctx;
46 : int ret;
47 : int i;
48 : struct {
49 : const char *name;
50 : const char *option;
51 : char **orig_list;
52 : char ***ctx_list;
53 1 : } lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL},
54 : {"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL},
55 : {"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL},
56 : {"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL},
57 : {NULL, NULL, NULL, NULL}};
58 :
59 1 : lists[0].ctx_list = &ctx->allow_users;
60 1 : lists[1].ctx_list = &ctx->deny_users;
61 1 : lists[2].ctx_list = &ctx->allow_groups;
62 1 : lists[3].ctx_list = &ctx->deny_groups;
63 :
64 1 : ret = sysdb_master_domain_update(bectx->domain);
65 1 : if (ret != EOK) {
66 0 : DEBUG(SSSDBG_FUNC_DATA, "Update of master domain failed [%d]: %s.\n",
67 : ret, sss_strerror(ret));
68 0 : goto failed;
69 : }
70 :
71 5 : for (i = 0; lists[i].name != NULL; i++) {
72 4 : ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path,
73 : lists[i].option, &lists[i].orig_list);
74 4 : if (ret == ENOENT) {
75 0 : DEBUG(SSSDBG_FUNC_DATA, "%s list is empty.\n", lists[i].name);
76 0 : *lists[i].ctx_list = NULL;
77 0 : continue;
78 4 : } else if (ret != EOK) {
79 0 : DEBUG(SSSDBG_CRIT_FAILURE, "confdb_get_string_as_list failed.\n");
80 0 : goto failed;
81 : }
82 :
83 4 : ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list,
84 : lists[i].ctx_list);
85 4 : if (ret != EOK) {
86 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse %s list [%d]: %s\n",
87 : lists[i].name, ret, sss_strerror(ret));
88 0 : goto failed;
89 : }
90 : }
91 :
92 1 : if (!ctx->allow_users &&
93 0 : !ctx->allow_groups &&
94 0 : !ctx->deny_users &&
95 0 : !ctx->deny_groups) {
96 0 : DEBUG(SSSDBG_OP_FAILURE,
97 : "No rules supplied for simple access provider. "
98 : "Access will be granted for all users.\n");
99 : }
100 1 : return EOK;
101 :
102 : failed:
103 0 : return ret;
104 : }
105 :
106 0 : void simple_access_handler(struct be_req *be_req)
107 : {
108 0 : struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
109 : struct pam_data *pd;
110 : struct tevent_req *req;
111 : struct simple_ctx *ctx;
112 : int ret;
113 : time_t now;
114 :
115 0 : pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
116 :
117 0 : pd->pam_status = PAM_SYSTEM_ERR;
118 :
119 0 : if (pd->cmd != SSS_PAM_ACCT_MGMT) {
120 0 : DEBUG(SSSDBG_CONF_SETTINGS,
121 : "simple access does not handle pam task %d.\n", pd->cmd);
122 0 : pd->pam_status = PAM_MODULE_UNKNOWN;
123 0 : goto done;
124 : }
125 :
126 0 : ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
127 : struct simple_ctx);
128 :
129 :
130 0 : now = time(NULL);
131 0 : if ((now - ctx->last_refresh_of_filter_lists)
132 : > TIMEOUT_OF_REFRESH_FILTER_LISTS) {
133 :
134 0 : ret = simple_access_obtain_filter_lists(ctx);
135 0 : if (ret != EOK) {
136 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to refresh filter lists\n");
137 : }
138 0 : ctx->last_refresh_of_filter_lists = now;
139 : }
140 :
141 0 : req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user);
142 0 : if (!req) {
143 0 : pd->pam_status = PAM_SYSTEM_ERR;
144 0 : goto done;
145 : }
146 0 : tevent_req_set_callback(req, simple_access_check, be_req);
147 0 : return;
148 :
149 : done:
150 0 : be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
151 : }
152 :
153 0 : static void simple_access_check(struct tevent_req *req)
154 : {
155 0 : bool access_granted = false;
156 : errno_t ret;
157 : struct pam_data *pd;
158 : struct be_req *be_req;
159 :
160 0 : be_req = tevent_req_callback_data(req, struct be_req);
161 0 : pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
162 :
163 0 : ret = simple_access_check_recv(req, &access_granted);
164 0 : talloc_free(req);
165 0 : if (ret != EOK) {
166 0 : pd->pam_status = PAM_SYSTEM_ERR;
167 0 : goto done;
168 : }
169 :
170 0 : if (access_granted) {
171 0 : pd->pam_status = PAM_SUCCESS;
172 : } else {
173 0 : pd->pam_status = PAM_PERM_DENIED;
174 : }
175 :
176 : done:
177 0 : be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
178 0 : }
179 :
180 4 : static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
181 : struct be_ctx *be_ctx,
182 : char **list,
183 : char ***_out)
184 : {
185 4 : TALLOC_CTX *tmp_ctx = NULL;
186 4 : char **out = NULL;
187 4 : char *domain = NULL;
188 4 : char *name = NULL;
189 : size_t size;
190 : size_t i;
191 : errno_t ret;
192 :
193 4 : if (list == NULL) {
194 0 : *_out = NULL;
195 0 : return EOK;
196 : }
197 :
198 4 : tmp_ctx = talloc_new(NULL);
199 4 : if (tmp_ctx == NULL) {
200 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
201 0 : ret = ENOMEM;
202 0 : goto done;
203 : }
204 :
205 4 : for (size = 0; list[size] != NULL; size++) {
206 : /* count size */
207 : }
208 :
209 4 : out = talloc_zero_array(tmp_ctx, char*, size + 1);
210 4 : if (out == NULL) {
211 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
212 0 : ret = ENOMEM;
213 0 : goto done;
214 : }
215 :
216 : /* Since this is access provider, we should fail on any error so we don't
217 : * allow unauthorized access. */
218 20 : for (i = 0; i < size; i++) {
219 16 : ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i],
220 : &domain, &name);
221 16 : if (ret != EOK) {
222 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
223 : list[i], ret, sss_strerror(ret));
224 0 : goto done;
225 : }
226 :
227 16 : if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 ||
228 0 : (be_ctx->domain->flat_name != NULL &&
229 0 : strcasecmp(domain, be_ctx->domain->flat_name) == 0)) {
230 : /* This object belongs to main SSSD domain. Those users and groups
231 : * are stored without domain part, so we will strip it off.
232 : * */
233 16 : out[i] = talloc_move(out, &name);
234 : } else {
235 : /* Subdomain users and groups are stored as fully qualified names,
236 : * thus we will remember the domain part.
237 : *
238 : * Since subdomains may come and go, we will look for their
239 : * existence later, during each access check.
240 : */
241 0 : out[i] = talloc_move(out, &list[i]);
242 : }
243 : }
244 :
245 4 : *_out = talloc_steal(mem_ctx, out);
246 4 : ret = EOK;
247 :
248 : done:
249 4 : talloc_free(tmp_ctx);
250 4 : return ret;
251 : }
252 :
253 : struct bet_ops simple_access_ops = {
254 : .handler = simple_access_handler,
255 : .finalize = NULL
256 : };
257 :
258 1 : int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops,
259 : void **pvt_data)
260 : {
261 1 : int ret = EINVAL;
262 : struct simple_ctx *ctx;
263 1 : ctx = talloc_zero(bectx, struct simple_ctx);
264 1 : if (ctx == NULL) {
265 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
266 0 : return ENOMEM;
267 : }
268 :
269 1 : ctx->domain = bectx->domain;
270 1 : ctx->be_ctx = bectx;
271 1 : ctx->last_refresh_of_filter_lists = 0;
272 :
273 1 : ret = simple_access_obtain_filter_lists(ctx);
274 1 : if (ret != EOK) {
275 0 : goto failed;
276 : }
277 :
278 1 : *ops = &simple_access_ops;
279 1 : *pvt_data = ctx;
280 :
281 1 : return EOK;
282 :
283 : failed:
284 0 : talloc_free(ctx);
285 0 : return ret;
286 : }
287 :
|