Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2015 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <errno.h>
22 : #include <talloc.h>
23 : #include <tevent.h>
24 :
25 : #include "util/util.h"
26 : #include "providers/be_ptask.h"
27 : #include "providers/ldap/sdap_sudo.h"
28 : #include "providers/ldap/sdap_sudo_shared.h"
29 : #include "db/sysdb_sudo.h"
30 :
31 : struct sdap_sudo_full_refresh_state {
32 : struct sdap_sudo_ctx *sudo_ctx;
33 : struct sdap_id_ctx *id_ctx;
34 : struct sysdb_ctx *sysdb;
35 : struct sss_domain_info *domain;
36 : int dp_error;
37 : };
38 :
39 : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq);
40 :
41 0 : struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
42 : struct sdap_sudo_ctx *sudo_ctx)
43 : {
44 0 : struct tevent_req *req = NULL;
45 0 : struct tevent_req *subreq = NULL;
46 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
47 0 : struct sdap_sudo_full_refresh_state *state = NULL;
48 0 : char *search_filter = NULL;
49 0 : char *delete_filter = NULL;
50 : int ret;
51 :
52 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_full_refresh_state);
53 0 : if (req == NULL) {
54 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
55 0 : return NULL;
56 : }
57 :
58 0 : state->sudo_ctx = sudo_ctx;
59 0 : state->id_ctx = id_ctx;
60 0 : state->sysdb = id_ctx->be->domain->sysdb;
61 0 : state->domain = id_ctx->be->domain;
62 :
63 : /* Download all rules from LDAP */
64 0 : search_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
65 0 : id_ctx->opts->sudorule_map[SDAP_OC_SUDORULE].name);
66 0 : if (search_filter == NULL) {
67 0 : ret = ENOMEM;
68 0 : goto immediately;
69 : }
70 :
71 : /* Remove all rules from cache */
72 0 : delete_filter = talloc_asprintf(state, "(%s=%s)",
73 : SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
74 0 : if (delete_filter == NULL) {
75 0 : ret = ENOMEM;
76 0 : goto immediately;
77 : }
78 :
79 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
80 :
81 0 : subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter,
82 : delete_filter);
83 0 : if (subreq == NULL) {
84 0 : ret = ENOMEM;
85 0 : goto immediately;
86 : }
87 :
88 0 : tevent_req_set_callback(subreq, sdap_sudo_full_refresh_done, req);
89 :
90 0 : return req;
91 :
92 : immediately:
93 0 : if (ret == EOK) {
94 0 : tevent_req_done(req);
95 : } else {
96 0 : tevent_req_error(req, ret);
97 : }
98 0 : tevent_req_post(req, id_ctx->be->ev);
99 :
100 0 : return req;
101 : }
102 :
103 0 : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
104 : {
105 0 : struct tevent_req *req = NULL;
106 0 : struct sdap_sudo_full_refresh_state *state = NULL;
107 : int ret;
108 :
109 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
110 0 : state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
111 :
112 0 : ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
113 0 : talloc_zfree(subreq);
114 0 : if (ret != EOK || state->dp_error != DP_ERR_OK) {
115 : goto done;
116 : }
117 :
118 : /* save the time in the sysdb */
119 0 : ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL));
120 0 : if (ret != EOK) {
121 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of "
122 : "a successful full refresh\n");
123 : /* this is only a minor error that does not affect the functionality,
124 : * therefore there is no need to report it with tevent_req_error()
125 : * which would cause problems in the consumers */
126 : }
127 :
128 0 : DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n");
129 :
130 : done:
131 0 : if (ret != EOK) {
132 0 : tevent_req_error(req, ret);
133 0 : return;
134 : }
135 :
136 0 : tevent_req_done(req);
137 : }
138 :
139 0 : int sdap_sudo_full_refresh_recv(struct tevent_req *req,
140 : int *dp_error)
141 : {
142 0 : struct sdap_sudo_full_refresh_state *state = NULL;
143 0 : state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
144 :
145 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
146 :
147 0 : *dp_error = state->dp_error;
148 :
149 0 : return EOK;
150 : }
151 :
152 : struct sdap_sudo_smart_refresh_state {
153 : struct sdap_id_ctx *id_ctx;
154 : struct sysdb_ctx *sysdb;
155 : int dp_error;
156 : };
157 :
158 : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq);
159 :
160 0 : struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
161 : struct sdap_sudo_ctx *sudo_ctx)
162 : {
163 0 : struct tevent_req *req = NULL;
164 0 : struct tevent_req *subreq = NULL;
165 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
166 0 : struct sdap_attr_map *map = id_ctx->opts->sudorule_map;
167 0 : struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
168 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
169 0 : char *search_filter = NULL;
170 : const char *usn;
171 : int ret;
172 :
173 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
174 0 : if (req == NULL) {
175 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
176 0 : return NULL;
177 : }
178 :
179 0 : state->id_ctx = id_ctx;
180 0 : state->sysdb = id_ctx->be->domain->sysdb;
181 :
182 : /* Download all rules from LDAP that are newer than usn */
183 0 : if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
184 0 : DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
185 0 : usn = "0";
186 0 : search_filter = talloc_asprintf(state, "(objectclass=%s)",
187 : map[SDAP_OC_SUDORULE].name);
188 : } else {
189 0 : usn = srv_opts->max_sudo_value;
190 0 : search_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%s))",
191 : map[SDAP_OC_SUDORULE].name,
192 0 : map[SDAP_AT_SUDO_USN].name, usn);
193 : }
194 0 : if (search_filter == NULL) {
195 0 : ret = ENOMEM;
196 0 : goto immediately;
197 : }
198 :
199 : /* Do not remove any rules that are already in the sysdb
200 : * sysdb_filter = NULL; */
201 :
202 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
203 : "(USN >= %s)\n", usn);
204 :
205 0 : subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter, NULL);
206 0 : if (subreq == NULL) {
207 0 : ret = ENOMEM;
208 0 : goto immediately;
209 : }
210 :
211 0 : tevent_req_set_callback(subreq, sdap_sudo_smart_refresh_done, req);
212 :
213 0 : return req;
214 :
215 : immediately:
216 0 : if (ret == EOK) {
217 0 : tevent_req_done(req);
218 : } else {
219 0 : tevent_req_error(req, ret);
220 : }
221 0 : tevent_req_post(req, id_ctx->be->ev);
222 :
223 0 : return req;
224 : }
225 :
226 0 : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
227 : {
228 0 : struct tevent_req *req = NULL;
229 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
230 : int ret;
231 :
232 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
233 0 : state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
234 :
235 0 : ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
236 0 : talloc_zfree(subreq);
237 0 : if (ret != EOK || state->dp_error != DP_ERR_OK) {
238 : goto done;
239 : }
240 :
241 0 : DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n");
242 :
243 : done:
244 0 : if (ret != EOK) {
245 0 : tevent_req_error(req, ret);
246 0 : return;
247 : }
248 :
249 0 : tevent_req_done(req);
250 : }
251 :
252 0 : int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
253 : int *dp_error)
254 : {
255 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
256 0 : state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
257 :
258 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
259 :
260 0 : *dp_error = state->dp_error;
261 :
262 0 : return EOK;
263 : }
264 :
265 : struct sdap_sudo_rules_refresh_state {
266 : struct sdap_id_ctx *id_ctx;
267 : size_t num_rules;
268 : int dp_error;
269 : bool deleted;
270 : };
271 :
272 : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq);
273 :
274 0 : struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
275 : struct sdap_sudo_ctx *sudo_ctx,
276 : char **rules)
277 : {
278 0 : struct tevent_req *req = NULL;
279 0 : struct tevent_req *subreq = NULL;
280 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
281 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
282 0 : struct sdap_options *opts = id_ctx->opts;
283 0 : TALLOC_CTX *tmp_ctx = NULL;
284 0 : char *search_filter = NULL;
285 0 : char *delete_filter = NULL;
286 0 : char *safe_rule = NULL;
287 : int ret;
288 : int i;
289 :
290 0 : if (rules == NULL) {
291 0 : return NULL;
292 : }
293 :
294 0 : tmp_ctx = talloc_new(NULL);
295 0 : if (tmp_ctx == NULL) {
296 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
297 0 : return NULL;
298 : }
299 :
300 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state);
301 0 : if (req == NULL) {
302 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
303 0 : return NULL;
304 : }
305 :
306 0 : search_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
307 0 : delete_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
308 :
309 : /* Download only selected rules from LDAP */
310 : /* Remove all selected rules from cache */
311 0 : for (i = 0; rules[i] != NULL; i++) {
312 0 : ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule);
313 0 : if (ret != EOK) {
314 0 : ret = ENOMEM;
315 0 : goto immediately;
316 : }
317 :
318 0 : search_filter = talloc_asprintf_append_buffer(search_filter, "(%s=%s)",
319 0 : opts->sudorule_map[SDAP_AT_SUDO_NAME].name,
320 : safe_rule);
321 0 : if (search_filter == NULL) {
322 0 : ret = ENOMEM;
323 0 : goto immediately;
324 : }
325 :
326 0 : delete_filter = talloc_asprintf_append_buffer(delete_filter, "(%s=%s)",
327 : SYSDB_SUDO_CACHE_AT_CN,
328 : safe_rule);
329 0 : if (delete_filter == NULL) {
330 0 : ret = ENOMEM;
331 0 : goto immediately;
332 : }
333 : }
334 :
335 0 : state->id_ctx = sudo_ctx->id_ctx;
336 0 : state->num_rules = i;
337 :
338 0 : search_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))",
339 0 : opts->sudorule_map[SDAP_OC_SUDORULE].name,
340 : search_filter);
341 0 : if (search_filter == NULL) {
342 0 : ret = ENOMEM;
343 0 : goto immediately;
344 : }
345 :
346 0 : delete_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))",
347 : SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC,
348 : delete_filter);
349 0 : if (delete_filter == NULL) {
350 0 : ret = ENOMEM;
351 0 : goto immediately;
352 : }
353 :
354 0 : subreq = sdap_sudo_refresh_send(req, sudo_ctx, search_filter,
355 : delete_filter);
356 0 : if (subreq == NULL) {
357 0 : ret = ENOMEM;
358 0 : goto immediately;
359 : }
360 :
361 0 : tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req);
362 :
363 0 : ret = EOK;
364 : immediately:
365 0 : talloc_free(tmp_ctx);
366 :
367 0 : if (ret != EOK) {
368 0 : tevent_req_error(req, ret);
369 0 : tevent_req_post(req, id_ctx->be->ev);
370 : }
371 :
372 0 : return req;
373 : }
374 :
375 0 : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
376 : {
377 0 : struct tevent_req *req = NULL;
378 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
379 : size_t downloaded_rules_num;
380 : int ret;
381 :
382 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
383 0 : state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
384 :
385 0 : ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
386 : &downloaded_rules_num);
387 0 : talloc_zfree(subreq);
388 0 : if (ret != EOK || state->dp_error != DP_ERR_OK) {
389 : goto done;
390 : }
391 :
392 0 : state->deleted = downloaded_rules_num != state->num_rules ? true : false;
393 :
394 : done:
395 0 : if (ret != EOK) {
396 0 : tevent_req_error(req, ret);
397 0 : return;
398 : }
399 :
400 0 : tevent_req_done(req);
401 : }
402 :
403 0 : int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
404 : int *dp_error,
405 : bool *deleted)
406 : {
407 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
408 0 : state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
409 :
410 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
411 :
412 0 : *dp_error = state->dp_error;
413 0 : *deleted = state->deleted;
414 :
415 0 : return EOK;
416 : }
417 :
418 : static struct tevent_req *
419 0 : sdap_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx,
420 : struct tevent_context *ev,
421 : struct be_ctx *be_ctx,
422 : struct be_ptask *be_ptask,
423 : void *pvt)
424 : {
425 : struct sdap_sudo_ctx *sudo_ctx;
426 0 : sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
427 :
428 0 : return sdap_sudo_full_refresh_send(mem_ctx, sudo_ctx);
429 : }
430 :
431 : static errno_t
432 0 : sdap_sudo_ptask_full_refresh_recv(struct tevent_req *req)
433 : {
434 : int dp_error;
435 :
436 0 : return sdap_sudo_full_refresh_recv(req, &dp_error);
437 : }
438 :
439 : static struct tevent_req *
440 0 : sdap_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx,
441 : struct tevent_context *ev,
442 : struct be_ctx *be_ctx,
443 : struct be_ptask *be_ptask,
444 : void *pvt)
445 : {
446 : struct sdap_sudo_ctx *sudo_ctx;
447 0 : sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
448 :
449 0 : return sdap_sudo_smart_refresh_send(mem_ctx, sudo_ctx);
450 : }
451 :
452 : static errno_t
453 0 : sdap_sudo_ptask_smart_refresh_recv(struct tevent_req *req)
454 : {
455 : int dp_error;
456 :
457 0 : return sdap_sudo_smart_refresh_recv(req, &dp_error);
458 : }
459 :
460 : errno_t
461 0 : sdap_sudo_ptask_setup(struct be_ctx *be_ctx, struct sdap_sudo_ctx *sudo_ctx)
462 : {
463 0 : return sdap_sudo_ptask_setup_generic(be_ctx, sudo_ctx->id_ctx->opts->basic,
464 : sdap_sudo_ptask_full_refresh_send,
465 : sdap_sudo_ptask_full_refresh_recv,
466 : sdap_sudo_ptask_smart_refresh_send,
467 : sdap_sudo_ptask_smart_refresh_recv,
468 : sudo_ctx);
469 : }
|