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