Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP handler for autofs
5 :
6 : Authors:
7 : Jakub Hrozek <jhrozek@redhat.com>
8 :
9 : Copyright (C) 2012 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 <errno.h>
26 : #include <tevent.h>
27 :
28 : #include "providers/ldap/ldap_common.h"
29 : #include "providers/ldap/sdap_autofs.h"
30 : #include "providers/ldap/sdap.h"
31 : #include "providers/ldap/sdap_async.h"
32 : #include "providers/backend.h"
33 : #include "providers/data_provider.h"
34 : #include "db/sysdb_autofs.h"
35 : #include "util/util.h"
36 :
37 : struct autofs_get_map_state {
38 : struct tevent_context *ev;
39 : struct sdap_id_ctx *ctx;
40 : struct sdap_id_op *op;
41 : const char *map_name;
42 :
43 : int dp_error;
44 : };
45 :
46 : static errno_t
47 : sdap_autofs_get_map_retry(struct tevent_req *req);
48 : static void
49 : sdap_autofs_get_map_connect_done(struct tevent_req *subreq);
50 : static void
51 : sdap_autofs_get_map_done(struct tevent_req *req);
52 :
53 : static struct tevent_req *
54 0 : sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx,
55 : struct tevent_context *ev,
56 : struct sdap_id_ctx *ctx,
57 : const char *map_name)
58 : {
59 : struct tevent_req *req;
60 : struct autofs_get_map_state *state;
61 : int ret;
62 :
63 0 : req = tevent_req_create(mem_ctx, &state, struct autofs_get_map_state);
64 0 : if (!req) return NULL;
65 :
66 0 : state->ev = ev;
67 0 : state->ctx = ctx;
68 0 : state->dp_error = DP_ERR_FATAL;
69 0 : state->map_name = map_name;
70 :
71 0 : state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
72 0 : if (!state->op) {
73 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
74 0 : ret = ENOMEM;
75 0 : goto fail;
76 : }
77 :
78 0 : ret = sdap_autofs_get_map_retry(req);
79 0 : if (ret != EOK) {
80 0 : goto fail;
81 : }
82 :
83 0 : return req;
84 :
85 : fail:
86 0 : tevent_req_error(req, ret);
87 0 : tevent_req_post(req, ev);
88 0 : return req;
89 : }
90 :
91 : static errno_t
92 0 : sdap_autofs_get_map_retry(struct tevent_req *req)
93 : {
94 0 : struct autofs_get_map_state *state =
95 0 : tevent_req_data(req, struct autofs_get_map_state);
96 : struct tevent_req *subreq;
97 0 : int ret = EOK;
98 :
99 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
100 0 : if (!subreq) {
101 0 : return ret;
102 : }
103 :
104 0 : tevent_req_set_callback(subreq, sdap_autofs_get_map_connect_done, req);
105 0 : return EOK;
106 : }
107 :
108 : static void
109 0 : sdap_autofs_get_map_connect_done(struct tevent_req *subreq)
110 : {
111 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
112 : struct tevent_req);
113 0 : struct autofs_get_map_state *state =
114 0 : tevent_req_data(req, struct autofs_get_map_state);
115 0 : int dp_error = DP_ERR_FATAL;
116 : int ret;
117 :
118 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
119 0 : talloc_zfree(subreq);
120 :
121 0 : if (ret != EOK) {
122 0 : state->dp_error = dp_error;
123 0 : tevent_req_error(req, ret);
124 0 : return;
125 : }
126 :
127 0 : subreq = sdap_autofs_setautomntent_send(state, state->ev,
128 0 : state->ctx->be->domain,
129 0 : state->ctx->be->domain->sysdb,
130 : sdap_id_op_handle(state->op),
131 : state->op,
132 0 : state->ctx->opts,
133 : state->map_name);
134 0 : if (!subreq) {
135 0 : DEBUG(SSSDBG_CRIT_FAILURE,
136 : "sdap_autofs_setautomntent_send failed\n");
137 0 : tevent_req_error(req, ENOMEM);
138 0 : return;
139 : }
140 0 : tevent_req_set_callback(subreq, sdap_autofs_get_map_done, req);
141 :
142 : }
143 :
144 : static void
145 0 : sdap_autofs_get_map_done(struct tevent_req *subreq)
146 : {
147 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
148 : struct tevent_req);
149 0 : struct autofs_get_map_state *state =
150 0 : tevent_req_data(req, struct autofs_get_map_state);
151 0 : int dp_error = DP_ERR_FATAL;
152 : int ret;
153 :
154 0 : ret = sdap_autofs_setautomntent_recv(subreq);
155 0 : talloc_zfree(subreq);
156 :
157 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
158 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
159 : /* retry */
160 0 : ret = sdap_autofs_get_map_retry(req);
161 0 : if (ret != EOK) {
162 0 : tevent_req_error(req, ret);
163 0 : return;
164 : }
165 0 : return;
166 : }
167 :
168 0 : if (ret && ret != ENOENT) {
169 0 : state->dp_error = dp_error;
170 0 : tevent_req_error(req, ret);
171 0 : return;
172 : }
173 :
174 0 : if (ret == ENOENT) {
175 0 : ret = sysdb_delete_autofsmap(state->ctx->be->domain, state->map_name);
176 0 : if (ret != EOK && ret != ENOENT) {
177 0 : DEBUG(SSSDBG_OP_FAILURE,
178 : "Cannot delete autofs map %s [%d]: %s\n",
179 : state->map_name, ret, strerror(ret));
180 0 : tevent_req_error(req, ret);
181 0 : return;
182 : }
183 : }
184 :
185 0 : state->dp_error = DP_ERR_OK;
186 0 : tevent_req_done(req);
187 : }
188 :
189 : static errno_t
190 0 : sdap_autofs_get_map_recv(struct tevent_req *req, int *dp_error_out)
191 : {
192 0 : struct autofs_get_map_state *state =
193 0 : tevent_req_data(req, struct autofs_get_map_state);
194 :
195 0 : if (dp_error_out) {
196 0 : *dp_error_out = state->dp_error;
197 : }
198 :
199 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
200 :
201 0 : return EOK;
202 : }
203 :
204 : struct sdap_autofs_handler_state {
205 : struct dp_reply_std reply;
206 : };
207 :
208 : static void sdap_autofs_handler_done(struct tevent_req *subreq);
209 :
210 : struct tevent_req *
211 0 : sdap_autofs_handler_send(TALLOC_CTX *mem_ctx,
212 : struct sdap_id_ctx *id_ctx,
213 : struct dp_autofs_data *data,
214 : struct dp_req_params *params)
215 : {
216 : struct sdap_autofs_handler_state *state;
217 : struct tevent_req *subreq;
218 : struct tevent_req *req;
219 : const char *master_map;
220 :
221 : errno_t ret;
222 :
223 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_autofs_handler_state);
224 0 : if (req == NULL) {
225 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
226 0 : return NULL;
227 : }
228 :
229 0 : DEBUG(SSSDBG_FUNC_DATA, "Requested refresh for: %s\n", data->mapname);
230 :
231 0 : master_map = dp_opt_get_string(id_ctx->opts->basic,
232 : SDAP_AUTOFS_MAP_MASTER_NAME);
233 0 : if (strcmp(master_map, data->mapname) == 0) {
234 0 : DEBUG(SSSDBG_FUNC_DATA, "Refresh of automount master map triggered: "
235 : "%s\n", data->mapname);
236 :
237 0 : ret = sysdb_invalidate_autofs_maps(id_ctx->be->domain);
238 0 : if (ret != EOK) {
239 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not invalidate autofs maps, "
240 : "backend might return stale entries\n");
241 : }
242 : }
243 :
244 0 : subreq = sdap_autofs_get_map_send(mem_ctx, params->ev,
245 : id_ctx, data->mapname);
246 0 : if (subreq == NULL) {
247 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request for %s.\n",
248 : data->mapname);
249 0 : ret = ENOMEM;
250 0 : goto immediately;
251 : }
252 :
253 0 : tevent_req_set_callback(subreq, sdap_autofs_handler_done, req);
254 :
255 0 : return req;
256 :
257 : immediately:
258 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
259 :
260 : /* TODO For backward compatibility we always return EOK to DP now. */
261 0 : tevent_req_done(req);
262 0 : tevent_req_post(req, params->ev);
263 :
264 0 : return req;
265 : }
266 :
267 0 : static void sdap_autofs_handler_done(struct tevent_req *subreq)
268 : {
269 : struct sdap_autofs_handler_state *state;
270 : struct tevent_req *req;
271 : int dp_error;
272 : errno_t ret;
273 :
274 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
275 0 : state = tevent_req_data(req, struct sdap_autofs_handler_state);
276 :
277 0 : ret = sdap_autofs_get_map_recv(subreq, &dp_error);
278 0 : talloc_zfree(subreq);
279 :
280 : /* TODO For backward compatibility we always return EOK to DP now. */
281 0 : dp_reply_std_set(&state->reply, dp_error, ret, NULL);
282 0 : tevent_req_done(req);
283 0 : }
284 :
285 : errno_t
286 0 : sdap_autofs_handler_recv(TALLOC_CTX *mem_ctx,
287 : struct tevent_req *req,
288 : struct dp_reply_std *data)
289 : {
290 0 : struct sdap_autofs_handler_state *state = NULL;
291 :
292 0 : state = tevent_req_data(req, struct sdap_autofs_handler_state);
293 :
294 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
295 :
296 0 : *data = state->reply;
297 :
298 0 : return EOK;
299 : }
300 :
301 0 : errno_t sdap_autofs_init(TALLOC_CTX *mem_ctx,
302 : struct be_ctx *be_ctx,
303 : struct sdap_id_ctx *id_ctx,
304 : struct dp_method *dp_methods)
305 : {
306 : errno_t ret;
307 :
308 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing autofs LDAP back end\n");
309 :
310 0 : ret = ldap_get_autofs_options(id_ctx, be_ctx->cdb, be_ctx->conf_path,
311 : id_ctx->opts);
312 0 : if (ret != EOK) {
313 0 : return ret;
314 : }
315 :
316 0 : dp_set_method(dp_methods, DPM_AUTOFS_HANDLER,
317 : sdap_autofs_handler_send, sdap_autofs_handler_recv, id_ctx,
318 : struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std);
319 :
320 0 : return EOK;
321 : }
|