Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2011 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 <string.h>
23 : #include <tevent.h>
24 :
25 : #include "providers/dp_backend.h"
26 : #include "providers/ldap/ldap_common.h"
27 : #include "providers/ldap/sdap.h"
28 : #include "providers/ldap/sdap_async.h"
29 : #include "providers/ldap/sdap_sudo.h"
30 : #include "providers/ldap/sdap_sudo_cache.h"
31 : #include "db/sysdb_sudo.h"
32 :
33 : #define SUDO_MAX_FIRST_REFRESH_DELAY 16
34 :
35 : struct sdap_sudo_full_refresh_state {
36 : struct sdap_sudo_ctx *sudo_ctx;
37 : struct sdap_id_ctx *id_ctx;
38 : struct sysdb_ctx *sysdb;
39 : struct sss_domain_info *domain;
40 : int dp_error;
41 : int error;
42 : };
43 :
44 : static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
45 : struct sdap_sudo_ctx *sudo_ctx);
46 :
47 : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq);
48 :
49 : static int sdap_sudo_full_refresh_recv(struct tevent_req *req,
50 : int *dp_error,
51 : int *error);
52 :
53 : struct sdap_sudo_rules_refresh_state {
54 : struct sdap_id_ctx *id_ctx;
55 : size_t num_rules;
56 : int dp_error;
57 : int error;
58 : };
59 :
60 : static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
61 : struct sdap_sudo_ctx *sudo_ctx,
62 : struct be_ctx *be_ctx,
63 : struct sdap_options *opts,
64 : struct sdap_id_conn_cache *conn_cache,
65 : char **rules);
66 :
67 : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq);
68 :
69 : static int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
70 : int *dp_error,
71 : int *error);
72 :
73 : struct sdap_sudo_smart_refresh_state {
74 : struct tevent_req *subreq;
75 : struct sdap_id_ctx *id_ctx;
76 : struct sysdb_ctx *sysdb;
77 : };
78 :
79 : static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
80 : struct sdap_sudo_ctx *sudo_ctx);
81 :
82 : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq);
83 :
84 : static int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
85 : int *dp_error,
86 : int *error);
87 :
88 : static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req);
89 :
90 : static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req);
91 :
92 : static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req);
93 :
94 : static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx,
95 : struct sdap_sudo_ctx *sudo_ctx,
96 : enum sdap_sudo_refresh_type refresh,
97 : tevent_req_fn callback,
98 : time_t delay,
99 : time_t timeout,
100 : struct tevent_req **_req);
101 :
102 : static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx,
103 : time_t delay);
104 :
105 : static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx,
106 : time_t delay);
107 :
108 : static void
109 0 : sdap_sudo_shutdown(struct be_req *req)
110 : {
111 0 : sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
112 0 : }
113 :
114 : struct bet_ops sdap_sudo_ops = {
115 : .handler = sdap_sudo_handler,
116 : .finalize = sdap_sudo_shutdown
117 : };
118 :
119 : static void sdap_sudo_get_hostinfo_done(struct tevent_req *req);
120 : static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx);
121 :
122 0 : int sdap_sudo_init(struct be_ctx *be_ctx,
123 : struct sdap_id_ctx *id_ctx,
124 : struct bet_ops **ops,
125 : void **pvt_data)
126 : {
127 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
128 0 : struct tevent_req *req = NULL;
129 : int ret;
130 :
131 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing sudo LDAP back end\n");
132 :
133 0 : sudo_ctx = talloc_zero(be_ctx, struct sdap_sudo_ctx);
134 0 : if (sudo_ctx == NULL) {
135 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n");
136 0 : return ENOMEM;
137 : }
138 :
139 0 : sudo_ctx->id_ctx = id_ctx;
140 0 : *ops = &sdap_sudo_ops;
141 0 : *pvt_data = sudo_ctx;
142 :
143 : /* we didn't do any full refresh now,
144 : * so we don't have current usn values available */
145 0 : sudo_ctx->full_refresh_done = false;
146 :
147 0 : ret = ldap_get_sudo_options(be_ctx->cdb,
148 : be_ctx->conf_path, id_ctx->opts,
149 : &sudo_ctx->use_host_filter,
150 : &sudo_ctx->include_regexp,
151 : &sudo_ctx->include_netgroups);
152 0 : if (ret != EOK) {
153 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot get SUDO options [%d]: %s\n",
154 : ret, strerror(ret));
155 0 : return ret;
156 : }
157 :
158 0 : req = sdap_sudo_get_hostinfo_send(sudo_ctx, id_ctx->opts, be_ctx);
159 0 : if (req == NULL) {
160 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve host information - "
161 : "(host filter will be disabled)\n");
162 :
163 0 : sudo_ctx->use_host_filter = false;
164 :
165 0 : ret = sdap_sudo_setup_periodical_refresh(sudo_ctx);
166 0 : if (ret != EOK) {
167 0 : DEBUG(SSSDBG_OP_FAILURE,
168 : "Unable to setup periodical refresh"
169 : "of sudo rules [%d]: %s\n", ret, strerror(ret));
170 : /* periodical updates will not work, but specific-rule update
171 : * is no affected by this, therefore we don't have to fail here */
172 : }
173 : } else {
174 0 : tevent_req_set_callback(req, sdap_sudo_get_hostinfo_done, sudo_ctx);
175 : }
176 :
177 0 : return EOK;
178 : }
179 :
180 0 : static void sdap_sudo_get_hostinfo_done(struct tevent_req *req)
181 : {
182 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
183 0 : char **hostnames = NULL;
184 0 : char **ip_addr = NULL;
185 : int ret;
186 :
187 0 : sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
188 :
189 0 : ret = sdap_sudo_get_hostinfo_recv(sudo_ctx, req, &hostnames, &ip_addr);
190 0 : talloc_zfree(req);
191 0 : if (ret != EOK) {
192 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve host information - "
193 : "(host filter will be disabled) [%d]: %s\n", ret, strerror(ret));
194 0 : sudo_ctx->use_host_filter = false;
195 : }
196 :
197 0 : talloc_zfree(sudo_ctx->hostnames);
198 0 : talloc_zfree(sudo_ctx->ip_addr);
199 :
200 0 : sudo_ctx->hostnames = talloc_move(sudo_ctx, &hostnames);
201 0 : sudo_ctx->ip_addr = talloc_move(sudo_ctx, &ip_addr);
202 :
203 0 : ret = sdap_sudo_setup_periodical_refresh(sudo_ctx);
204 0 : if (ret != EOK) {
205 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh"
206 : "of sudo rules [%d]: %s\n", ret, strerror(ret));
207 : }
208 0 : }
209 :
210 0 : static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx)
211 : {
212 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
213 : time_t smart_default;
214 : time_t smart_interval;
215 : time_t full_interval;
216 : time_t last_full;
217 : time_t delay;
218 : int ret;
219 :
220 0 : smart_interval = dp_opt_get_int(id_ctx->opts->basic,
221 : SDAP_SUDO_SMART_REFRESH_INTERVAL);
222 :
223 0 : full_interval = dp_opt_get_int(id_ctx->opts->basic,
224 : SDAP_SUDO_FULL_REFRESH_INTERVAL);
225 :
226 0 : if (smart_interval == 0 && full_interval == 0) {
227 0 : smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number;
228 :
229 0 : DEBUG(SSSDBG_MINOR_FAILURE, "At least one periodical update has to be "
230 : "enabled. Setting smart refresh interval to default value (%ld).\n",
231 : smart_default);
232 :
233 0 : ret = dp_opt_set_int(id_ctx->opts->basic,
234 : SDAP_SUDO_SMART_REFRESH_INTERVAL,
235 : smart_default);
236 0 : if (ret != EOK) {
237 0 : return ret;
238 : }
239 : }
240 :
241 0 : if (full_interval <= smart_interval) {
242 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Full refresh interval has to be greater"
243 : "than smart refresh interval. Periodical full refresh will be "
244 : "disabled.\n");
245 0 : ret = dp_opt_set_int(id_ctx->opts->basic,
246 : SDAP_SUDO_FULL_REFRESH_INTERVAL,
247 : 0);
248 0 : if (ret != EOK) {
249 0 : return ret;
250 : }
251 : }
252 :
253 0 : ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->domain,
254 : &last_full);
255 0 : if (ret != EOK) {
256 0 : return ret;
257 : }
258 :
259 0 : if (last_full == 0) {
260 : /* If this is the first startup, we need to kick off
261 : * an refresh immediately, to close a window where
262 : * clients requesting sudo information won't get an
263 : * immediate reply with no entries
264 : */
265 0 : delay = 0;
266 : } else {
267 : /* At least one update has previously run,
268 : * so clients will get cached data.
269 : * We will delay the refresh so we don't slow
270 : * down the startup process if this is happening
271 : * during system boot.
272 : */
273 :
274 : /* delay at least by 10s */
275 0 : delay = 10;
276 : }
277 :
278 0 : ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
279 : SDAP_SUDO_REFRESH_FULL,
280 : sdap_sudo_periodical_first_refresh_done,
281 : delay, full_interval, NULL);
282 0 : if (ret != EOK) {
283 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
284 : "rules! Periodical updates will not work!\n");
285 0 : return ret;
286 : }
287 :
288 0 : return EOK;
289 : }
290 :
291 0 : static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
292 : {
293 : unsigned int usn_number;
294 0 : char *endptr = NULL;
295 :
296 0 : if (srv_opts != NULL && usn != NULL) {
297 0 : talloc_zfree(srv_opts->max_sudo_value);
298 0 : srv_opts->max_sudo_value = talloc_steal(srv_opts, usn);
299 :
300 0 : usn_number = strtoul(usn, &endptr, 10);
301 0 : if ((endptr == NULL || (*endptr == '\0' && endptr != usn))
302 0 : && (usn_number > srv_opts->last_usn)) {
303 0 : srv_opts->last_usn = usn_number;
304 : }
305 :
306 0 : DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
307 : srv_opts->max_sudo_value);
308 : } else {
309 0 : DEBUG(SSSDBG_TRACE_FUNC, "srv_opts is NULL\n");
310 : }
311 0 : }
312 :
313 0 : static char *sdap_sudo_build_host_filter(TALLOC_CTX *mem_ctx,
314 : struct sdap_attr_map *map,
315 : char **hostnames,
316 : char **ip_addr,
317 : bool netgroups,
318 : bool regexp)
319 : {
320 0 : TALLOC_CTX *tmp_ctx = NULL;
321 0 : char *filter = NULL;
322 : int i;
323 :
324 0 : tmp_ctx = talloc_new(NULL);
325 0 : if (tmp_ctx == NULL) {
326 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
327 0 : return NULL;
328 : }
329 :
330 0 : filter = talloc_strdup(tmp_ctx, "(|");
331 0 : if (filter == NULL) {
332 0 : goto done;
333 : }
334 :
335 : /* sudoHost is not specified */
336 0 : filter = talloc_asprintf_append_buffer(filter, "(!(%s=*))",
337 0 : map[SDAP_AT_SUDO_HOST].name);
338 0 : if (filter == NULL) {
339 0 : goto done;
340 : }
341 :
342 : /* ALL */
343 0 : filter = talloc_asprintf_append_buffer(filter, "(%s=ALL)",
344 0 : map[SDAP_AT_SUDO_HOST].name);
345 0 : if (filter == NULL) {
346 0 : goto done;
347 : }
348 :
349 : /* hostnames */
350 0 : if (hostnames != NULL) {
351 0 : for (i = 0; hostnames[i] != NULL; i++) {
352 0 : filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
353 0 : map[SDAP_AT_SUDO_HOST].name,
354 0 : hostnames[i]);
355 0 : if (filter == NULL) {
356 0 : goto done;
357 : }
358 : }
359 : }
360 :
361 : /* ip addresses and networks */
362 0 : if (ip_addr != NULL) {
363 0 : for (i = 0; ip_addr[i] != NULL; i++) {
364 0 : filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
365 0 : map[SDAP_AT_SUDO_HOST].name,
366 0 : ip_addr[i]);
367 0 : if (filter == NULL) {
368 0 : goto done;
369 : }
370 : }
371 : }
372 :
373 : /* sudoHost contains netgroup - will be filtered more by sudo */
374 0 : if (netgroups) {
375 0 : filter = talloc_asprintf_append_buffer(filter, SDAP_SUDO_FILTER_NETGROUP,
376 0 : map[SDAP_AT_SUDO_HOST].name,
377 : "*");
378 0 : if (filter == NULL) {
379 0 : goto done;
380 : }
381 : }
382 :
383 : /* sudoHost contains regexp - will be filtered more by sudo */
384 : /* from sudo match.c :
385 : * #define has_meta(s) (strpbrk(s, "\\?*[]") != NULL)
386 : */
387 0 : if (regexp) {
388 0 : filter = talloc_asprintf_append_buffer(filter,
389 : "(|(%s=*\\\\*)(%s=*?*)(%s=*\\2A*)"
390 : "(%s=*[*]*))",
391 0 : map[SDAP_AT_SUDO_HOST].name,
392 0 : map[SDAP_AT_SUDO_HOST].name,
393 0 : map[SDAP_AT_SUDO_HOST].name,
394 0 : map[SDAP_AT_SUDO_HOST].name);
395 0 : if (filter == NULL) {
396 0 : goto done;
397 : }
398 : }
399 :
400 0 : filter = talloc_strdup_append_buffer(filter, ")");
401 0 : if (filter == NULL) {
402 0 : goto done;
403 : }
404 :
405 0 : talloc_steal(mem_ctx, filter);
406 :
407 : done:
408 0 : talloc_free(tmp_ctx);
409 :
410 0 : return filter;
411 : }
412 :
413 0 : static char *sdap_sudo_get_filter(TALLOC_CTX *mem_ctx,
414 : struct sdap_attr_map *map,
415 : struct sdap_sudo_ctx *sudo_ctx,
416 : const char *rule_filter)
417 : {
418 0 : TALLOC_CTX *tmp_ctx = NULL;
419 0 : char *host_filter = NULL;
420 0 : char *filter = NULL;
421 :
422 0 : if (!sudo_ctx->use_host_filter) {
423 0 : return talloc_strdup(mem_ctx, rule_filter);
424 : }
425 :
426 0 : tmp_ctx = talloc_new(NULL);
427 0 : if (tmp_ctx == NULL) {
428 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
429 0 : return NULL;
430 : }
431 :
432 0 : host_filter = sdap_sudo_build_host_filter(tmp_ctx, map,
433 : sudo_ctx->hostnames,
434 : sudo_ctx->ip_addr,
435 0 : sudo_ctx->include_netgroups,
436 0 : sudo_ctx->include_regexp);
437 0 : if (host_filter == NULL) {
438 0 : goto done;
439 : }
440 :
441 0 : filter = sdap_get_id_specific_filter(tmp_ctx, rule_filter, host_filter);
442 0 : if (filter == NULL) {
443 0 : goto done;
444 : }
445 :
446 0 : talloc_steal(mem_ctx, filter);
447 :
448 : done:
449 0 : talloc_free(tmp_ctx);
450 0 : return filter;
451 : }
452 :
453 0 : static void sdap_sudo_reply(struct tevent_req *req)
454 : {
455 0 : struct be_req *be_req = NULL;
456 0 : struct be_sudo_req *sudo_req = NULL;
457 0 : int dp_error = DP_ERR_OK;
458 0 : int error = EOK;
459 : int ret;
460 :
461 0 : be_req = tevent_req_callback_data(req, struct be_req);
462 0 : sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
463 :
464 0 : switch (sudo_req->type) {
465 : case BE_REQ_SUDO_FULL:
466 0 : ret = sdap_sudo_full_refresh_recv(req, &dp_error, &error);
467 0 : break;
468 : case BE_REQ_SUDO_RULES:
469 0 : ret = sdap_sudo_rules_refresh_recv(req, &dp_error, &error);
470 0 : break;
471 : default:
472 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
473 : sudo_req->type);
474 0 : ret = EINVAL;
475 : }
476 :
477 0 : talloc_zfree(req);
478 0 : if (ret != EOK) {
479 0 : sdap_handler_done(be_req, DP_ERR_FATAL, ret, strerror(ret));
480 0 : return;
481 : }
482 :
483 0 : sdap_handler_done(be_req, dp_error, error, strerror(error));
484 : }
485 :
486 0 : void sdap_sudo_handler(struct be_req *be_req)
487 : {
488 0 : struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
489 0 : struct tevent_req *req = NULL;
490 0 : struct be_sudo_req *sudo_req = NULL;
491 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
492 0 : struct sdap_id_ctx *id_ctx = NULL;
493 0 : int ret = EOK;
494 :
495 0 : sudo_ctx = talloc_get_type(be_ctx->bet_info[BET_SUDO].pvt_bet_data,
496 : struct sdap_sudo_ctx);
497 0 : id_ctx = sudo_ctx->id_ctx;
498 :
499 0 : sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
500 :
501 0 : switch (sudo_req->type) {
502 : case BE_REQ_SUDO_FULL:
503 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
504 0 : req = sdap_sudo_full_refresh_send(be_req, sudo_ctx);
505 0 : break;
506 : case BE_REQ_SUDO_RULES:
507 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
508 0 : req = sdap_sudo_rules_refresh_send(be_req, sudo_ctx, id_ctx->be,
509 0 : id_ctx->opts, id_ctx->conn->conn_cache,
510 : sudo_req->rules);
511 0 : break;
512 : default:
513 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
514 : sudo_req->type);
515 0 : ret = EINVAL;
516 0 : goto fail;
517 : }
518 :
519 0 : if (req == NULL) {
520 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n",
521 : sudo_req->type);
522 0 : ret = ENOMEM;
523 0 : goto fail;
524 : }
525 :
526 0 : tevent_req_set_callback(req, sdap_sudo_reply, be_req);
527 :
528 0 : return;
529 :
530 : fail:
531 0 : sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
532 : }
533 :
534 : /* issue full refresh of sudo rules */
535 0 : static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
536 : struct sdap_sudo_ctx *sudo_ctx)
537 : {
538 0 : struct tevent_req *req = NULL;
539 0 : struct tevent_req *subreq = NULL;
540 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
541 0 : struct sdap_sudo_full_refresh_state *state = NULL;
542 0 : char *ldap_filter = NULL;
543 0 : char *ldap_full_filter = NULL;
544 0 : char *sysdb_filter = NULL;
545 : int ret;
546 :
547 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_full_refresh_state);
548 0 : if (req == NULL) {
549 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
550 0 : return NULL;
551 : }
552 :
553 0 : sudo_ctx->full_refresh_in_progress = true;
554 :
555 0 : state->sudo_ctx = sudo_ctx;
556 0 : state->id_ctx = id_ctx;
557 0 : state->sysdb = id_ctx->be->domain->sysdb;
558 0 : state->domain = id_ctx->be->domain;
559 :
560 : /* Download all rules from LDAP */
561 0 : ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
562 0 : id_ctx->opts->sudorule_map[SDAP_OC_SUDORULE].name);
563 0 : if (ldap_filter == NULL) {
564 0 : ret = ENOMEM;
565 0 : goto immediately;
566 : }
567 :
568 0 : ldap_full_filter = sdap_sudo_get_filter(state, id_ctx->opts->sudorule_map,
569 : sudo_ctx, ldap_filter);
570 0 : if (ldap_full_filter == NULL) {
571 0 : ret = ENOMEM;
572 0 : goto immediately;
573 : }
574 :
575 : /* Remove all rules from cache */
576 0 : sysdb_filter = talloc_asprintf(state, "(%s=%s)",
577 : SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
578 0 : if (sysdb_filter == NULL) {
579 0 : ret = ENOMEM;
580 0 : goto immediately;
581 : }
582 :
583 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
584 :
585 0 : subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts,
586 0 : id_ctx->conn->conn_cache,
587 : ldap_full_filter, sysdb_filter);
588 0 : if (subreq == NULL) {
589 0 : ret = ENOMEM;
590 0 : goto immediately;
591 : }
592 :
593 0 : tevent_req_set_callback(subreq, sdap_sudo_full_refresh_done, req);
594 :
595 : /* free filters */
596 0 : talloc_free(ldap_filter);
597 0 : talloc_free(ldap_full_filter);
598 0 : talloc_free(sysdb_filter);
599 :
600 0 : return req;
601 :
602 : immediately:
603 0 : if (ret == EOK) {
604 0 : tevent_req_done(req);
605 : } else {
606 0 : tevent_req_error(req, ret);
607 : }
608 0 : tevent_req_post(req, id_ctx->be->ev);
609 :
610 0 : return req;
611 : }
612 :
613 0 : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
614 : {
615 0 : struct tevent_req *req = NULL;
616 0 : struct sdap_sudo_full_refresh_state *state = NULL;
617 0 : char *highest_usn = NULL;
618 : int ret;
619 :
620 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
621 0 : state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
622 :
623 0 : ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
624 : &state->error, &highest_usn, NULL);
625 0 : talloc_zfree(subreq);
626 0 : if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
627 : goto done;
628 : }
629 :
630 0 : state->sudo_ctx->full_refresh_done = true;
631 :
632 : /* save the time in the sysdb */
633 0 : ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL));
634 0 : if (ret != EOK) {
635 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of "
636 : "a successful full refresh\n");
637 : /* this is only a minor error that does not affect the functionality,
638 : * therefore there is no need to report it with tevent_req_error()
639 : * which would cause problems in the consumers */
640 : }
641 :
642 0 : DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n");
643 :
644 : /* set highest usn */
645 0 : if (highest_usn != NULL) {
646 0 : sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
647 : }
648 :
649 : done:
650 0 : state->sudo_ctx->full_refresh_in_progress = false;
651 :
652 0 : if (ret != EOK) {
653 0 : tevent_req_error(req, ret);
654 0 : return;
655 : }
656 :
657 0 : tevent_req_done(req);
658 : }
659 :
660 0 : static int sdap_sudo_full_refresh_recv(struct tevent_req *req,
661 : int *dp_error,
662 : int *error)
663 : {
664 0 : struct sdap_sudo_full_refresh_state *state = NULL;
665 0 : state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
666 :
667 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
668 :
669 0 : *dp_error = state->dp_error;
670 0 : *error = state->error;
671 :
672 0 : return EOK;
673 : }
674 :
675 : /* issue refresh of specific sudo rules */
676 0 : static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
677 : struct sdap_sudo_ctx *sudo_ctx,
678 : struct be_ctx *be_ctx,
679 : struct sdap_options *opts,
680 : struct sdap_id_conn_cache *conn_cache,
681 : char **rules)
682 : {
683 0 : struct tevent_req *req = NULL;
684 0 : struct tevent_req *subreq = NULL;
685 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
686 0 : TALLOC_CTX *tmp_ctx = NULL;
687 0 : char *ldap_filter = NULL;
688 0 : char *ldap_full_filter = NULL;
689 0 : char *sysdb_filter = NULL;
690 0 : char *safe_rule = NULL;
691 : int ret;
692 : int i;
693 :
694 0 : if (rules == NULL) {
695 0 : return NULL;
696 : }
697 :
698 0 : tmp_ctx = talloc_new(NULL);
699 0 : if (tmp_ctx == NULL) {
700 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
701 0 : return NULL;
702 : }
703 :
704 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state);
705 0 : if (req == NULL) {
706 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
707 0 : return NULL;
708 : }
709 :
710 0 : ldap_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
711 0 : sysdb_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
712 :
713 : /* Download only selected rules from LDAP */
714 : /* Remove all selected rules from cache */
715 0 : for (i = 0; rules[i] != NULL; i++) {
716 0 : ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule);
717 0 : if (ret != EOK) {
718 0 : ret = ENOMEM;
719 0 : goto immediately;
720 : }
721 :
722 0 : ldap_filter = talloc_asprintf_append_buffer(ldap_filter, "(%s=%s)",
723 0 : opts->sudorule_map[SDAP_AT_SUDO_NAME].name,
724 : safe_rule);
725 0 : if (ldap_filter == NULL) {
726 0 : ret = ENOMEM;
727 0 : goto immediately;
728 : }
729 :
730 0 : sysdb_filter = talloc_asprintf_append_buffer(sysdb_filter, "(%s=%s)",
731 : SYSDB_SUDO_CACHE_AT_CN,
732 : safe_rule);
733 0 : if (sysdb_filter == NULL) {
734 0 : ret = ENOMEM;
735 0 : goto immediately;
736 : }
737 : }
738 :
739 0 : state->id_ctx = sudo_ctx->id_ctx;
740 0 : state->num_rules = i;
741 :
742 0 : ldap_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))",
743 0 : opts->sudorule_map[SDAP_OC_SUDORULE].name,
744 : ldap_filter);
745 0 : if (ldap_filter == NULL) {
746 0 : ret = ENOMEM;
747 0 : goto immediately;
748 : }
749 :
750 0 : ldap_full_filter = sdap_sudo_get_filter(tmp_ctx, opts->sudorule_map,
751 : sudo_ctx, ldap_filter);
752 0 : if (ldap_full_filter == NULL) {
753 0 : ret = ENOMEM;
754 0 : goto immediately;
755 : }
756 :
757 0 : sysdb_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))",
758 : SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC,
759 : sysdb_filter);
760 0 : if (sysdb_filter == NULL) {
761 0 : ret = ENOMEM;
762 0 : goto immediately;
763 : }
764 :
765 0 : subreq = sdap_sudo_refresh_send(req, be_ctx, opts, conn_cache,
766 : ldap_full_filter, sysdb_filter);
767 0 : if (subreq == NULL) {
768 0 : ret = ENOMEM;
769 0 : goto immediately;
770 : }
771 :
772 0 : tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req);
773 :
774 0 : ret = EOK;
775 : immediately:
776 0 : talloc_free(tmp_ctx);
777 :
778 0 : if (ret != EOK) {
779 0 : tevent_req_error(req, ret);
780 0 : tevent_req_post(req, be_ctx->ev);
781 : }
782 :
783 0 : return req;
784 : }
785 :
786 0 : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
787 : {
788 0 : struct tevent_req *req = NULL;
789 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
790 0 : char *highest_usn = NULL;
791 : size_t downloaded_rules_num;
792 : int ret;
793 :
794 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
795 0 : state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
796 :
797 0 : ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error,
798 : &highest_usn, &downloaded_rules_num);
799 0 : talloc_zfree(subreq);
800 0 : if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
801 : goto done;
802 : }
803 :
804 : /* set highest usn */
805 0 : if (highest_usn != NULL) {
806 0 : sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
807 : }
808 :
809 0 : if (downloaded_rules_num != state->num_rules) {
810 0 : state->error = ENOENT;
811 : }
812 :
813 : done:
814 0 : if (ret != EOK) {
815 0 : tevent_req_error(req, ret);
816 0 : return;
817 : }
818 :
819 0 : tevent_req_done(req);
820 : }
821 :
822 0 : static int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
823 : int *dp_error,
824 : int *error)
825 : {
826 0 : struct sdap_sudo_rules_refresh_state *state = NULL;
827 0 : state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
828 :
829 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
830 :
831 0 : *dp_error = state->dp_error;
832 0 : *error = state->error;
833 :
834 0 : return EOK;
835 : }
836 :
837 : /* issue smart refresh of sudo rules */
838 0 : static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
839 : struct sdap_sudo_ctx *sudo_ctx)
840 : {
841 0 : struct tevent_req *req = NULL;
842 0 : struct tevent_req *subreq = NULL;
843 0 : struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
844 0 : struct sdap_attr_map *map = id_ctx->opts->sudorule_map;
845 0 : struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
846 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
847 0 : char *ldap_filter = NULL;
848 0 : char *ldap_full_filter = NULL;
849 : const char *usn;
850 : int ret;
851 :
852 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
853 0 : if (req == NULL) {
854 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
855 0 : return NULL;
856 : }
857 :
858 0 : if (!sudo_ctx->full_refresh_done
859 0 : && (srv_opts == NULL || srv_opts->max_sudo_value == 0)) {
860 : /* Perform full refresh first */
861 0 : DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, "
862 : "waiting for full refresh!\n");
863 0 : ret = EINVAL;
864 0 : goto immediately;
865 : }
866 :
867 0 : state->id_ctx = id_ctx;
868 0 : state->sysdb = id_ctx->be->domain->sysdb;
869 :
870 : /* Download all rules from LDAP that are newer than usn */
871 0 : usn = srv_opts->max_sudo_value;
872 0 : if (usn != NULL) {
873 0 : ldap_filter = talloc_asprintf(state,
874 : "(&(objectclass=%s)(%s>=%s)(!(%s=%s)))",
875 : map[SDAP_OC_SUDORULE].name,
876 0 : map[SDAP_AT_SUDO_USN].name, usn,
877 0 : map[SDAP_AT_SUDO_USN].name, usn);
878 : } else {
879 : /* no valid USN value known */
880 0 : ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
881 : map[SDAP_OC_SUDORULE].name);
882 : }
883 0 : if (ldap_filter == NULL) {
884 0 : ret = ENOMEM;
885 0 : goto immediately;
886 : }
887 :
888 0 : ldap_full_filter = sdap_sudo_get_filter(state, map, sudo_ctx, ldap_filter);
889 0 : if (ldap_full_filter == NULL) {
890 0 : ret = ENOMEM;
891 0 : goto immediately;
892 : }
893 :
894 : /* Do not remove any rules that are already in the sysdb
895 : * sysdb_filter = NULL; */
896 :
897 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
898 : "(USN > %s)\n", (usn == NULL ? "0" : usn));
899 :
900 0 : subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts,
901 0 : id_ctx->conn->conn_cache,
902 : ldap_full_filter, NULL);
903 0 : if (subreq == NULL) {
904 0 : ret = ENOMEM;
905 0 : goto immediately;
906 : }
907 :
908 0 : state->subreq = subreq;
909 0 : tevent_req_set_callback(subreq, sdap_sudo_smart_refresh_done, req);
910 :
911 : /* free filters */
912 0 : talloc_free(ldap_filter);
913 0 : talloc_free(ldap_full_filter);
914 :
915 0 : return req;
916 :
917 : immediately:
918 0 : if (ret == EOK) {
919 0 : tevent_req_done(req);
920 : } else {
921 0 : tevent_req_error(req, ret);
922 : }
923 0 : tevent_req_post(req, id_ctx->be->ev);
924 :
925 0 : return req;
926 : }
927 :
928 0 : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
929 : {
930 0 : struct tevent_req *req = NULL;
931 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
932 0 : char *highest_usn = NULL;
933 : int dp_error;
934 : int error;
935 : int ret;
936 :
937 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
938 0 : state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
939 :
940 0 : ret = sdap_sudo_refresh_recv(state, subreq, &dp_error, &error,
941 : &highest_usn, NULL);
942 0 : if (ret != EOK || dp_error != DP_ERR_OK || error != EOK) {
943 : goto done;
944 : }
945 :
946 0 : DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n");
947 :
948 : /* set highest usn */
949 0 : if (highest_usn != NULL) {
950 0 : sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
951 : }
952 :
953 : done:
954 0 : if (ret != EOK) {
955 0 : tevent_req_error(req, ret);
956 0 : return;
957 : }
958 :
959 0 : tevent_req_done(req);
960 : }
961 :
962 0 : static int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
963 : int *dp_error,
964 : int *error)
965 : {
966 0 : struct sdap_sudo_smart_refresh_state *state = NULL;
967 0 : state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
968 :
969 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
970 :
971 0 : return sdap_sudo_refresh_recv(state, state->subreq, dp_error, error,
972 : NULL, NULL);
973 : }
974 :
975 0 : static void sdap_sudo_full_refresh_online_cb(void *pvt)
976 : {
977 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
978 : time_t timeout;
979 : int ret;
980 :
981 0 : sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
982 :
983 : /* remove online callback */
984 0 : talloc_zfree(sudo_ctx->first_refresh_online_cb);
985 :
986 : /* schedule new first refresh only if this callback wasn't triggered
987 : * by ongoing full refresh */
988 0 : if (sudo_ctx->full_refresh_in_progress) {
989 0 : return;
990 : }
991 :
992 : /* otherwise cancel the concurrent timer for full refresh */
993 0 : talloc_zfree(sudo_ctx->first_refresh_timer);
994 :
995 : /* and fire full refresh immediately */
996 0 : timeout = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
997 : SDAP_SUDO_FULL_REFRESH_INTERVAL);
998 0 : if (timeout == 0) {
999 : /* runtime configuration change? */
1000 0 : DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
1001 : "is disabled\n");
1002 0 : return;
1003 : }
1004 :
1005 0 : ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
1006 : SDAP_SUDO_REFRESH_FULL,
1007 : sdap_sudo_periodical_first_refresh_done,
1008 : 0, timeout, NULL);
1009 0 : if (ret != EOK) {
1010 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
1011 : "rules! Periodical updates will not work!\n");
1012 : }
1013 : }
1014 :
1015 0 : static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req)
1016 : {
1017 0 : struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */
1018 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
1019 : time_t delay;
1020 : time_t timeout;
1021 0 : int dp_error = DP_ERR_OK;
1022 0 : int error = EOK;
1023 : int ret;
1024 :
1025 0 : ret = sdap_sudo_timer_recv(req, req, &subreq);
1026 0 : if (ret != EOK) {
1027 0 : DEBUG(SSSDBG_OP_FAILURE,
1028 : "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
1029 0 : goto schedule;
1030 : }
1031 :
1032 0 : ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error);
1033 0 : if (ret != EOK) {
1034 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
1035 : "failed [%d]: %s)\n", ret, strerror(ret));
1036 0 : goto schedule;
1037 : }
1038 :
1039 0 : if (dp_error != DP_ERR_OK || error != EOK) {
1040 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
1041 : "failed [dp_error: %d] ([%d]: %s)\n",
1042 : dp_error, error, strerror(error));
1043 0 : goto schedule;
1044 : }
1045 :
1046 : schedule:
1047 0 : sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
1048 0 : if (sudo_ctx->first_refresh_timer == req) {
1049 0 : sudo_ctx->first_refresh_timer = NULL;
1050 : }
1051 0 : talloc_zfree(req);
1052 :
1053 : /* full refresh */
1054 0 : delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
1055 : SDAP_SUDO_FULL_REFRESH_INTERVAL);
1056 0 : if (delay == 0) {
1057 : /* runtime configuration change? */
1058 0 : DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
1059 : "is disabled\n");
1060 0 : return;
1061 : }
1062 :
1063 : /* if we are offline, we will try to perform another full refresh */
1064 0 : if (dp_error == DP_ERR_OFFLINE) {
1065 0 : sudo_ctx->full_refresh_attempts++;
1066 0 : timeout = delay;
1067 0 : delay = sudo_ctx->full_refresh_attempts << 1;
1068 0 : if (delay > SUDO_MAX_FIRST_REFRESH_DELAY) {
1069 0 : delay = SUDO_MAX_FIRST_REFRESH_DELAY;
1070 : }
1071 :
1072 0 : DEBUG(SSSDBG_TRACE_FUNC, "Data provider is offline. "
1073 : "Scheduling another full refresh in %ld minutes.\n", delay);
1074 :
1075 0 : ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
1076 : SDAP_SUDO_REFRESH_FULL,
1077 : sdap_sudo_periodical_first_refresh_done,
1078 : delay * 60, timeout,
1079 : &sudo_ctx->first_refresh_timer);
1080 0 : if (ret != EOK) {
1081 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
1082 : "rules! Periodical updates will not work!\n");
1083 : }
1084 :
1085 : /* also setup online callback to make sure the refresh is fired as soon
1086 : * as possible */
1087 0 : ret = be_add_online_cb(sudo_ctx->id_ctx->be, sudo_ctx->id_ctx->be,
1088 : sdap_sudo_full_refresh_online_cb,
1089 : sudo_ctx, &sudo_ctx->first_refresh_online_cb);
1090 0 : if (ret != EOK) {
1091 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set up online callback\n");
1092 : }
1093 :
1094 0 : return;
1095 : }
1096 :
1097 0 : ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay);
1098 0 : if (ret != EOK) {
1099 0 : DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n");
1100 : }
1101 :
1102 : /* smart refresh */
1103 0 : delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
1104 : SDAP_SUDO_SMART_REFRESH_INTERVAL);
1105 0 : if (delay == 0) {
1106 : /* runtime configuration change? */
1107 0 : DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules "
1108 : "is disabled\n");
1109 0 : return;
1110 : }
1111 :
1112 0 : ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay);
1113 0 : if (ret != EOK) {
1114 0 : DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n");
1115 : }
1116 : }
1117 :
1118 0 : static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req)
1119 : {
1120 0 : struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */
1121 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
1122 : time_t delay;
1123 0 : int dp_error = DP_ERR_FATAL;
1124 0 : int error = EFAULT;
1125 : int ret;
1126 :
1127 0 : ret = sdap_sudo_timer_recv(req, req, &subreq);
1128 0 : if (ret != EOK) {
1129 0 : DEBUG(SSSDBG_OP_FAILURE,
1130 : "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
1131 0 : goto schedule;
1132 : }
1133 :
1134 0 : ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error);
1135 0 : if (ret != EOK) {
1136 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
1137 : "failed [%d]: %s)\n", ret, strerror(ret));
1138 0 : goto schedule;
1139 : }
1140 :
1141 0 : if (dp_error != DP_ERR_OK || error != EOK) {
1142 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
1143 : "failed [dp_error: %d] ([%d]: %s)\n",
1144 : dp_error, error, strerror(error));
1145 0 : goto schedule;
1146 : }
1147 :
1148 : schedule:
1149 0 : sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
1150 0 : talloc_zfree(req);
1151 :
1152 0 : delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
1153 : SDAP_SUDO_FULL_REFRESH_INTERVAL);
1154 0 : if (delay == 0) {
1155 : /* runtime configuration change? */
1156 0 : DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
1157 : "is disabled\n");
1158 0 : return;
1159 : }
1160 :
1161 0 : ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay);
1162 0 : if (ret != EOK) {
1163 0 : DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n");
1164 : }
1165 : }
1166 :
1167 0 : static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req)
1168 : {
1169 0 : struct tevent_req *subreq = NULL; /* req from sdap_sudo_smart_refresh_send() */
1170 0 : struct sdap_sudo_ctx *sudo_ctx = NULL;
1171 : time_t delay;
1172 : int dp_error;
1173 : int error;
1174 : int ret;
1175 :
1176 0 : ret = sdap_sudo_timer_recv(req, req, &subreq);
1177 0 : if (ret != EOK) {
1178 0 : DEBUG(SSSDBG_OP_FAILURE,
1179 : "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
1180 0 : goto schedule;
1181 : }
1182 :
1183 0 : ret = sdap_sudo_smart_refresh_recv(subreq, &dp_error, &error);
1184 0 : if (ret != EOK) {
1185 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules "
1186 : "failed [%d]: %s\n", ret, strerror(ret));
1187 : }
1188 :
1189 0 : if (dp_error != DP_ERR_OK || error != EOK) {
1190 0 : DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules "
1191 : "failed [dp_error: %d] ([%d]: %s)\n",
1192 : dp_error, error, strerror(error));
1193 0 : goto schedule;
1194 : }
1195 :
1196 : schedule:
1197 0 : sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
1198 0 : talloc_zfree(req);
1199 :
1200 0 : delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
1201 : SDAP_SUDO_SMART_REFRESH_INTERVAL);
1202 0 : if (delay == 0) {
1203 : /* runtime configuration change? */
1204 0 : DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules "
1205 : "is disabled\n");
1206 0 : return;
1207 : }
1208 :
1209 0 : ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay);
1210 0 : if (ret != EOK) {
1211 0 : DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n");
1212 : }
1213 : }
1214 :
1215 0 : static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx,
1216 : struct sdap_sudo_ctx *sudo_ctx,
1217 : enum sdap_sudo_refresh_type refresh,
1218 : tevent_req_fn callback,
1219 : time_t delay,
1220 : time_t timeout,
1221 : struct tevent_req **_req)
1222 : {
1223 0 : struct tevent_req *req = NULL;
1224 0 : sdap_sudo_timer_fn_t send_fn = NULL;
1225 0 : const char *name = NULL;
1226 : struct timeval when;
1227 :
1228 0 : when = tevent_timeval_current_ofs(delay, 0);
1229 :
1230 0 : switch (refresh) {
1231 : case SDAP_SUDO_REFRESH_FULL:
1232 0 : send_fn = sdap_sudo_full_refresh_send;
1233 0 : name = "Full refresh";
1234 0 : break;
1235 : case SDAP_SUDO_REFRESH_SMART:
1236 0 : send_fn = sdap_sudo_smart_refresh_send;
1237 0 : name = "Smart refresh";
1238 0 : break;
1239 : case SDAP_SUDO_REFRESH_RULES:
1240 0 : DEBUG(SSSDBG_OP_FAILURE, "Rules refresh can't be scheduled!\n");
1241 0 : return EINVAL;
1242 : default:
1243 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unknown refresh type [%d].\n", refresh);
1244 0 : return EINVAL;
1245 : }
1246 :
1247 :
1248 :
1249 0 : req = sdap_sudo_timer_send(mem_ctx, sudo_ctx->id_ctx->be->ev, sudo_ctx,
1250 : when, timeout, send_fn);
1251 0 : if (req == NULL) {
1252 0 : return ENOMEM;
1253 : }
1254 :
1255 0 : tevent_req_set_callback(req, callback, sudo_ctx);
1256 :
1257 0 : DEBUG(SSSDBG_TRACE_FUNC, "%s scheduled at: %lld\n",
1258 : name, (long long)when.tv_sec);
1259 :
1260 0 : if (_req != NULL) {
1261 0 : *_req = req;
1262 : }
1263 :
1264 0 : return EOK;
1265 : }
1266 :
1267 0 : static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx,
1268 : time_t delay)
1269 : {
1270 : int ret;
1271 :
1272 0 : ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
1273 : SDAP_SUDO_REFRESH_FULL,
1274 : sdap_sudo_periodical_full_refresh_done,
1275 : delay, delay, NULL);
1276 0 : if (ret != EOK) {
1277 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
1278 : "rules!\n");
1279 0 : return ret;
1280 : }
1281 :
1282 0 : return EOK;
1283 : }
1284 :
1285 0 : static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx,
1286 : time_t delay)
1287 : {
1288 : int ret;
1289 :
1290 0 : ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
1291 : SDAP_SUDO_REFRESH_SMART,
1292 : sdap_sudo_periodical_smart_refresh_done,
1293 : delay, delay, NULL);
1294 0 : if (ret != EOK) {
1295 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule smart refresh of sudo "
1296 : "rules!\n");
1297 0 : return ret;
1298 : }
1299 :
1300 0 : return EOK;
1301 : }
|