Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Identity Enumeration
5 :
6 : Authors:
7 : Simo Sorce <ssorce@redhat.com>
8 :
9 : Copyright (C) 2009 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "util/util.h"
26 : #include "db/sysdb.h"
27 : #include "providers/ldap/ldap_common.h"
28 : #include "providers/ldap/sdap_async_enum.h"
29 :
30 : #define LDAP_ENUM_PURGE_TIMEOUT 10800
31 :
32 0 : errno_t ldap_setup_enumeration(struct be_ctx *be_ctx,
33 : struct sdap_options *opts,
34 : struct sdap_domain *sdom,
35 : be_ptask_send_t send_fn,
36 : be_ptask_recv_t recv_fn,
37 : void *pvt)
38 : {
39 : errno_t ret;
40 : time_t first_delay;
41 : time_t period;
42 : time_t cleanup;
43 : bool has_enumerated;
44 : struct ldap_enum_ctx *ectx;
45 :
46 0 : ret = sysdb_has_enumerated(sdom->dom, &has_enumerated);
47 0 : if (ret == ENOENT) {
48 : /* default value */
49 0 : has_enumerated = false;
50 0 : } else if (ret != EOK) {
51 0 : return ret;
52 : }
53 :
54 0 : if (has_enumerated) {
55 : /* At least one enumeration has previously run,
56 : * so clients will get cached data. We will delay
57 : * starting to enumerate by 10s so we don't slow
58 : * down the startup process if this is happening
59 : * during system boot.
60 : */
61 0 : first_delay = 10;
62 : } else {
63 : /* This is our first startup. Schedule the
64 : * enumeration to start immediately once we
65 : * enter the mainloop.
66 : */
67 0 : first_delay = 0;
68 : }
69 :
70 0 : cleanup = dp_opt_get_int(opts->basic, SDAP_PURGE_CACHE_TIMEOUT);
71 0 : if (cleanup == 0) {
72 : /* We need to cleanup the cache once in a while when enumerating, otherwise
73 : * enumeration would only download deltas since the previous lastUSN and would
74 : * not detect removed entries
75 : */
76 0 : ret = dp_opt_set_int(opts->basic, SDAP_PURGE_CACHE_TIMEOUT,
77 : LDAP_ENUM_PURGE_TIMEOUT);
78 0 : if (ret != EOK) {
79 0 : DEBUG(SSSDBG_CRIT_FAILURE,
80 : "Cannot set cleanup timeout, enumeration wouldn't "
81 : "detect removed entries!\n");
82 0 : return ret;
83 : }
84 : }
85 :
86 0 : period = dp_opt_get_int(opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
87 :
88 0 : ectx = talloc(sdom, struct ldap_enum_ctx);
89 0 : if (ectx == NULL) {
90 0 : return ENOMEM;
91 : }
92 0 : ectx->sdom = sdom;
93 0 : ectx->pvt = pvt;
94 :
95 0 : ret = be_ptask_create(sdom, be_ctx,
96 : period, /* period */
97 : first_delay, /* first_delay */
98 : 5, /* enabled delay */
99 : 0, /* random offset */
100 : period, /* timeout */
101 : BE_PTASK_OFFLINE_SKIP,
102 : 0, /* max_backoff */
103 : send_fn, recv_fn,
104 : ectx, "enumeration", &sdom->enum_task);
105 0 : if (ret != EOK) {
106 0 : DEBUG(SSSDBG_FATAL_FAILURE,
107 : "Unable to initialize enumeration periodic task\n");
108 0 : talloc_free(ectx);
109 0 : return ret;
110 : }
111 :
112 0 : talloc_steal(sdom->enum_task, ectx);
113 0 : return EOK;
114 : }
115 :
116 : struct ldap_enumeration_state {
117 : struct ldap_enum_ctx *ectx;
118 : struct sdap_id_ctx *id_ctx;
119 : struct sss_domain_info *dom;
120 : };
121 :
122 : static void ldap_enumeration_done(struct tevent_req *subreq);
123 :
124 : struct tevent_req *
125 0 : ldap_enumeration_send(TALLOC_CTX *mem_ctx,
126 : struct tevent_context *ev,
127 : struct be_ctx *be_ctx,
128 : struct be_ptask *be_ptask,
129 : void *pvt)
130 : {
131 : struct ldap_enumeration_state *state;
132 : struct tevent_req *req;
133 : struct tevent_req *subreq;
134 : struct ldap_enum_ctx *ectx;
135 : errno_t ret;
136 :
137 0 : req = tevent_req_create(mem_ctx, &state,
138 : struct ldap_enumeration_state);
139 0 : if (req == NULL) {
140 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
141 0 : return NULL;
142 : }
143 :
144 0 : ectx = talloc_get_type(pvt, struct ldap_enum_ctx);
145 0 : if (ectx == NULL) {
146 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot retrieve ldap_enum_ctx!\n");
147 0 : ret = EFAULT;
148 0 : goto fail;
149 : }
150 0 : state->ectx = ectx;
151 0 : state->dom = ectx->sdom->dom;
152 0 : state->id_ctx = talloc_get_type_abort(ectx->pvt, struct sdap_id_ctx);
153 :
154 0 : subreq = sdap_dom_enum_send(state, ev, state->id_ctx, ectx->sdom,
155 0 : state->id_ctx->conn);
156 0 : if (subreq == NULL) {
157 : /* The ptask API will reschedule the enumeration on its own on
158 : * failure */
159 0 : DEBUG(SSSDBG_OP_FAILURE,
160 : "Failed to schedule enumeration, retrying later!\n");
161 0 : ret = EIO;
162 0 : goto fail;
163 : }
164 :
165 0 : tevent_req_set_callback(subreq, ldap_enumeration_done, req);
166 0 : return req;
167 :
168 : fail:
169 0 : tevent_req_error(req, ret);
170 0 : tevent_req_post(req, ev);
171 0 : return req;
172 : }
173 :
174 : static void
175 0 : ldap_enumeration_done(struct tevent_req *subreq)
176 : {
177 : errno_t ret;
178 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
179 : struct tevent_req);
180 :
181 0 : ret = sdap_dom_enum_recv(subreq);
182 0 : talloc_zfree(subreq);
183 0 : if (ret != EOK) {
184 0 : tevent_req_error(req, ret);
185 0 : return;
186 : }
187 :
188 0 : tevent_req_done(req);
189 : }
190 :
191 : errno_t
192 0 : ldap_enumeration_recv(struct tevent_req *req)
193 : {
194 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
195 :
196 0 : return EOK;
197 : }
|