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 <time.h>
23 : #include <talloc.h>
24 :
25 : #include "util/util.h"
26 : #include "providers/be_ptask.h"
27 : #include "providers/ldap/sdap.h"
28 : #include "providers/ldap/sdap_sudo_shared.h"
29 : #include "db/sysdb_sudo.h"
30 :
31 : errno_t
32 0 : sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
33 : struct dp_option *opts,
34 : be_ptask_send_t full_send_fn,
35 : be_ptask_recv_t full_recv_fn,
36 : be_ptask_send_t smart_send_fn,
37 : be_ptask_recv_t smart_recv_fn,
38 : void *pvt)
39 : {
40 : time_t smart;
41 : time_t full;
42 : time_t delay;
43 : time_t last_refresh;
44 : errno_t ret;
45 :
46 0 : smart = dp_opt_get_int(opts, SDAP_SUDO_SMART_REFRESH_INTERVAL);
47 0 : full = dp_opt_get_int(opts, SDAP_SUDO_FULL_REFRESH_INTERVAL);
48 :
49 0 : if (smart == 0 && full == 0) {
50 : /* We don't allow both types to be disabled. At least smart refresh
51 : * needs to be enabled. In this case smart refresh will catch up new
52 : * and modified rules and deleted rules are caught when expired. */
53 0 : smart = opts[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number;
54 :
55 0 : DEBUG(SSSDBG_CONF_SETTINGS, "At least smart refresh needs to be "
56 : "enabled. Setting smart refresh interval to default value "
57 : "(%ld) seconds.\n", smart);
58 0 : } else if (full > 0 && full <= smart) {
59 : /* In this case it does not make any sense to run smart refresh. */
60 0 : smart = 0;
61 :
62 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Smart refresh interval has to be lower "
63 : "than full refresh interval. Periodical smart refresh will be "
64 : "disabled.\n");
65 : }
66 :
67 0 : ret = sysdb_sudo_get_last_full_refresh(be_ctx->domain, &last_refresh);
68 0 : if (ret != EOK) {
69 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to obtain time of last full "
70 : "refresh. Assuming none was performed so far.\n");
71 0 : last_refresh = 0;
72 : }
73 :
74 0 : if (last_refresh == 0) {
75 : /* If this is the first startup, we need to kick off an refresh
76 : * immediately, to close a window where clients requesting sudo
77 : * information won't get an immediate reply with no entries */
78 0 : delay = 0;
79 : } else {
80 : /* At least one update has previously run, so clients will get cached
81 : * data. We will delay the refresh so we don't slow down the startup
82 : * process if this is happening during system boot. */
83 0 : delay = 10;
84 : }
85 :
86 : /* Full refresh.
87 : *
88 : * Disable when offline and run immediately when SSSD goes back online.
89 : * Since we have periodical online check we don't have to run this task
90 : * when offline. */
91 0 : if (full > 0) {
92 0 : ret = be_ptask_create(be_ctx, be_ctx, full, delay, 0, 0, full,
93 : BE_PTASK_OFFLINE_DISABLE, 0,
94 : full_send_fn, full_recv_fn, pvt,
95 : "SUDO Full Refresh", NULL);
96 0 : if (ret != EOK) {
97 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup full refresh ptask "
98 : "[%d]: %s\n", ret, sss_strerror(ret));
99 0 : return ret;
100 : }
101 : }
102 :
103 : /* Smart refresh.
104 : *
105 : * Disable when offline and reschedule normally when SSSD goes back online.
106 : * Since we have periodical online check we don't have to run this task
107 : * when offline. */
108 0 : if (smart > 0) {
109 0 : ret = be_ptask_create(be_ctx, be_ctx, smart, delay + smart, smart, 0,
110 : smart, BE_PTASK_OFFLINE_DISABLE, 0,
111 : smart_send_fn, smart_recv_fn, pvt,
112 : "SUDO Smart Refresh", NULL);
113 0 : if (ret != EOK) {
114 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup smart refresh ptask "
115 : "[%d]: %s\n", ret, sss_strerror(ret));
116 0 : return ret;
117 : }
118 : }
119 :
120 0 : return EOK;
121 : }
122 :
123 : static char *
124 0 : sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
125 : unsigned long usn,
126 : const char *leftover)
127 : {
128 0 : const char *str = leftover == NULL ? "" : leftover;
129 : char *newusn;
130 :
131 : /* We increment USN number so that we can later use simplify filter
132 : * (just usn >= last+1 instaed of usn >= last && usn != last).
133 : */
134 0 : usn++;
135 :
136 : /* Convert back to string appending non-converted values since it
137 : * is an indicator that modifyTimestamp is used instead of entryUSN.
138 : * modifyTimestamp contains also timezone specification, usually Z.
139 : * We can't really handle any errors here so we just use what we got. */
140 0 : newusn = talloc_asprintf(mem_ctx, "%lu%s", usn, str);
141 0 : if (newusn == NULL) {
142 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
143 0 : return NULL;
144 : }
145 :
146 0 : return newusn;
147 : }
148 :
149 : void
150 0 : sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
151 : const char *usn)
152 : {
153 : unsigned long usn_number;
154 : char *newusn;
155 0 : char *endptr = NULL;
156 : errno_t ret;
157 :
158 0 : if (srv_opts == NULL) {
159 0 : DEBUG(SSSDBG_TRACE_FUNC, "Bug: srv_opts is NULL\n");
160 0 : return;
161 : }
162 :
163 0 : if (usn == NULL) {
164 0 : DEBUG(SSSDBG_TRACE_FUNC, "Bug: usn is NULL\n");
165 0 : return;
166 : }
167 :
168 0 : errno = 0;
169 0 : usn_number = strtoul(usn, &endptr, 10);
170 0 : if (errno != 0) {
171 0 : ret = errno;
172 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s [%d]: %s\n",
173 : usn, ret, sss_strerror(ret));
174 0 : return;
175 : }
176 :
177 0 : newusn = sdap_sudo_new_usn(srv_opts, usn_number, endptr);
178 0 : if (newusn == NULL) {
179 0 : return;
180 : }
181 :
182 0 : if (sysdb_compare_usn(newusn, srv_opts->max_sudo_value) > 0) {
183 0 : talloc_zfree(srv_opts->max_sudo_value);
184 0 : srv_opts->max_sudo_value = newusn;
185 : } else {
186 0 : talloc_zfree(newusn);
187 : }
188 :
189 0 : if (usn_number > srv_opts->last_usn) {
190 0 : srv_opts->last_usn = usn_number;
191 : }
192 :
193 0 : DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
194 : srv_opts->max_sudo_value);
195 : }
|