Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2013 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 <talloc.h>
22 : #include <tevent.h>
23 :
24 : #include "providers/ldap/sdap.h"
25 : #include "providers/ldap/ldap_common.h"
26 :
27 : struct sdap_refresh_state {
28 : struct tevent_context *ev;
29 : struct be_ctx *be_ctx;
30 : struct be_acct_req *account_req;
31 : struct sdap_id_ctx *id_ctx;
32 : struct sdap_domain *sdom;
33 : const char *type;
34 : char **names;
35 : size_t index;
36 : };
37 :
38 : static errno_t sdap_refresh_step(struct tevent_req *req);
39 : static void sdap_refresh_done(struct tevent_req *subreq);
40 :
41 0 : static struct tevent_req *sdap_refresh_send(TALLOC_CTX *mem_ctx,
42 : struct tevent_context *ev,
43 : struct be_ctx *be_ctx,
44 : struct sss_domain_info *domain,
45 : int entry_type,
46 : char **names,
47 : void *pvt)
48 : {
49 0 : struct sdap_refresh_state *state = NULL;
50 0 : struct tevent_req *req = NULL;
51 : errno_t ret;
52 :
53 0 : req = tevent_req_create(mem_ctx, &state,
54 : struct sdap_refresh_state);
55 0 : if (req == NULL) {
56 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
57 0 : return NULL;
58 : }
59 :
60 0 : if (names == NULL) {
61 0 : ret = EOK;
62 0 : goto immediately;
63 : }
64 :
65 0 : state->ev = ev;
66 0 : state->be_ctx = be_ctx;
67 0 : state->id_ctx = talloc_get_type(pvt, struct sdap_id_ctx);
68 0 : state->names = names;
69 0 : state->index = 0;
70 :
71 0 : state->sdom = sdap_domain_get(state->id_ctx->opts, domain);
72 0 : if (state->sdom == NULL) {
73 0 : ret = ERR_DOMAIN_NOT_FOUND;
74 0 : goto immediately;
75 : }
76 :
77 0 : switch (entry_type) {
78 : case BE_REQ_USER:
79 0 : state->type = "user";
80 0 : break;
81 : case BE_REQ_GROUP:
82 0 : state->type = "group";
83 0 : break;
84 : case BE_REQ_NETGROUP:
85 0 : state->type = "netgroup";
86 0 : break;
87 : default:
88 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid entry type [%d]!\n", entry_type);
89 : }
90 :
91 0 : state->account_req = talloc_zero(state, struct be_acct_req);
92 0 : if (state->account_req == NULL) {
93 0 : ret = ENOMEM;
94 0 : goto immediately;
95 : }
96 :
97 0 : state->account_req->entry_type = entry_type;
98 0 : state->account_req->attr_type = BE_ATTR_CORE;
99 0 : state->account_req->filter_type = BE_FILTER_NAME;
100 0 : state->account_req->extra_value = NULL;
101 0 : state->account_req->domain = domain->name;
102 : /* filter will be filled later */
103 :
104 0 : ret = sdap_refresh_step(req);
105 0 : if (ret == EOK) {
106 0 : DEBUG(SSSDBG_TRACE_FUNC, "Nothing to refresh\n");
107 0 : goto immediately;
108 0 : } else if (ret != EAGAIN) {
109 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_refresh_step() failed "
110 : "[%d]: %s\n", ret, sss_strerror(ret));
111 0 : goto immediately;
112 : }
113 :
114 0 : return req;
115 :
116 : immediately:
117 0 : if (ret == EOK) {
118 0 : tevent_req_done(req);
119 : } else {
120 0 : tevent_req_error(req, ret);
121 : }
122 0 : tevent_req_post(req, ev);
123 :
124 0 : return req;
125 : }
126 :
127 0 : static errno_t sdap_refresh_step(struct tevent_req *req)
128 : {
129 0 : struct sdap_refresh_state *state = NULL;
130 0 : struct tevent_req *subreq = NULL;
131 : errno_t ret;
132 :
133 0 : state = tevent_req_data(req, struct sdap_refresh_state);
134 :
135 0 : if (state->names == NULL) {
136 0 : ret = EOK;
137 0 : goto done;
138 : }
139 :
140 0 : state->account_req->filter_value = state->names[state->index];
141 0 : if (state->account_req->filter_value == NULL) {
142 0 : ret = EOK;
143 0 : goto done;
144 : }
145 :
146 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing refresh of %s %s\n",
147 : state->type, state->account_req->filter_value);
148 :
149 0 : subreq = sdap_handle_acct_req_send(state, state->be_ctx,
150 : state->account_req, state->id_ctx,
151 0 : state->sdom, state->id_ctx->conn, true);
152 0 : if (subreq == NULL) {
153 0 : ret = ENOMEM;
154 0 : goto done;
155 : }
156 :
157 0 : tevent_req_set_callback(subreq, sdap_refresh_done, req);
158 :
159 0 : state->index++;
160 0 : ret = EAGAIN;
161 :
162 : done:
163 0 : return ret;
164 : }
165 :
166 0 : static void sdap_refresh_done(struct tevent_req *subreq)
167 : {
168 0 : struct sdap_refresh_state *state = NULL;
169 0 : struct tevent_req *req = NULL;
170 0 : const char *err_msg = NULL;
171 : errno_t dp_error;
172 : int sdap_ret;
173 : errno_t ret;
174 :
175 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
176 0 : state = tevent_req_data(req, struct sdap_refresh_state);
177 :
178 0 : ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err_msg, &sdap_ret);
179 0 : talloc_zfree(subreq);
180 0 : if (ret != EOK) {
181 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, "
182 : "sdap_ret: %d, errno: %d]: %s\n", state->type,
183 : dp_error, sdap_ret, ret, err_msg);
184 0 : goto done;
185 : }
186 :
187 0 : ret = sdap_refresh_step(req);
188 0 : if (ret == EAGAIN) {
189 0 : return;
190 : }
191 :
192 : done:
193 0 : if (ret != EOK) {
194 0 : tevent_req_error(req, ret);
195 0 : return;
196 : }
197 :
198 0 : tevent_req_done(req);
199 : }
200 :
201 0 : static errno_t sdap_refresh_recv(struct tevent_req *req)
202 : {
203 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
204 :
205 0 : return EOK;
206 : }
207 :
208 : static struct tevent_req *
209 0 : sdap_refresh_users_send(TALLOC_CTX *mem_ctx,
210 : struct tevent_context *ev,
211 : struct be_ctx *be_ctx,
212 : struct sss_domain_info *domain,
213 : char **names,
214 : void *pvt)
215 : {
216 0 : return sdap_refresh_send(mem_ctx, ev, be_ctx, domain,
217 : BE_REQ_USER, names, pvt);
218 : }
219 :
220 0 : static errno_t sdap_refresh_users_recv(struct tevent_req *req)
221 : {
222 0 : return sdap_refresh_recv(req);
223 : }
224 :
225 : static struct tevent_req *
226 0 : sdap_refresh_groups_send(TALLOC_CTX *mem_ctx,
227 : struct tevent_context *ev,
228 : struct be_ctx *be_ctx,
229 : struct sss_domain_info *domain,
230 : char **names,
231 : void *pvt)
232 : {
233 0 : return sdap_refresh_send(mem_ctx, ev, be_ctx, domain,
234 : BE_REQ_GROUP, names, pvt);
235 : }
236 :
237 0 : static errno_t sdap_refresh_groups_recv(struct tevent_req *req)
238 : {
239 0 : return sdap_refresh_recv(req);
240 : }
241 :
242 : static struct tevent_req *
243 0 : sdap_refresh_netgroups_send(TALLOC_CTX *mem_ctx,
244 : struct tevent_context *ev,
245 : struct be_ctx *be_ctx,
246 : struct sss_domain_info *domain,
247 : char **names,
248 : void *pvt)
249 : {
250 0 : return sdap_refresh_send(mem_ctx, ev, be_ctx, domain,
251 : BE_REQ_NETGROUP, names, pvt);
252 : }
253 :
254 0 : static errno_t sdap_refresh_netgroups_recv(struct tevent_req *req)
255 : {
256 0 : return sdap_refresh_recv(req);
257 : }
258 :
259 0 : errno_t sdap_refresh_init(struct be_refresh_ctx *refresh_ctx,
260 : struct sdap_id_ctx *id_ctx)
261 : {
262 : errno_t ret;
263 :
264 0 : ret = be_refresh_add_cb(refresh_ctx, BE_REFRESH_TYPE_USERS,
265 : sdap_refresh_users_send,
266 : sdap_refresh_users_recv,
267 : id_ctx);
268 0 : if (ret != EOK && ret != EEXIST) {
269 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh of users "
270 : "will not work [%d]: %s\n", ret, strerror(ret));
271 : }
272 :
273 0 : ret = be_refresh_add_cb(refresh_ctx, BE_REFRESH_TYPE_GROUPS,
274 : sdap_refresh_groups_send,
275 : sdap_refresh_groups_recv,
276 : id_ctx);
277 0 : if (ret != EOK && ret != EEXIST) {
278 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh of groups "
279 : "will not work [%d]: %s\n", ret, strerror(ret));
280 : }
281 :
282 0 : ret = be_refresh_add_cb(refresh_ctx, BE_REFRESH_TYPE_NETGROUPS,
283 : sdap_refresh_netgroups_send,
284 : sdap_refresh_netgroups_recv,
285 : id_ctx);
286 0 : if (ret != EOK && ret != EEXIST) {
287 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh of netgroups "
288 : "will not work [%d]: %s\n", ret, strerror(ret));
289 : }
290 :
291 0 : return ret;
292 : }
|