Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2016 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 <talloc.h>
23 : #include <tevent.h>
24 : #include "util/util.h"
25 : #include "providers/backend.h"
26 : #include "providers/ldap/sdap_async.h"
27 : #include "providers/ldap/ldap_common.h"
28 :
29 : struct sdap_online_check_state {
30 : struct sdap_id_ctx *id_ctx;
31 : struct be_ctx *be_ctx;
32 : };
33 :
34 : static void sdap_online_check_connect_done(struct tevent_req *subreq);
35 : static void sdap_online_check_reinit_done(struct tevent_req *subreq);
36 :
37 0 : static struct tevent_req *sdap_online_check_send(TALLOC_CTX *mem_ctx,
38 : struct sdap_id_ctx *id_ctx)
39 : {
40 : struct sdap_online_check_state *state;
41 : struct tevent_req *subreq;
42 : struct tevent_req *req;
43 : struct be_ctx *be_ctx;
44 : errno_t ret;
45 :
46 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_online_check_state);
47 0 : if (req == NULL) {
48 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
49 0 : return NULL;
50 : }
51 :
52 0 : state->id_ctx = id_ctx;
53 0 : state->be_ctx = be_ctx = id_ctx->be;
54 :
55 0 : subreq = sdap_cli_connect_send(state, be_ctx->ev, id_ctx->opts, be_ctx,
56 0 : id_ctx->conn->service, false,
57 : CON_TLS_DFL, false);
58 0 : if (subreq == NULL) {
59 0 : ret = ENOMEM;
60 0 : goto immediately;
61 : }
62 :
63 0 : tevent_req_set_callback(subreq, sdap_online_check_connect_done, req);
64 :
65 0 : return req;
66 :
67 : immediately:
68 0 : if (ret == EOK) {
69 0 : tevent_req_done(req);
70 : } else {
71 0 : tevent_req_error(req, ret);
72 : }
73 0 : tevent_req_post(req, be_ctx->ev);
74 :
75 0 : return req;
76 : }
77 :
78 0 : static void sdap_online_check_connect_done(struct tevent_req *subreq)
79 : {
80 : struct sdap_online_check_state *state;
81 : struct sdap_server_opts *srv_opts;
82 : struct sdap_id_ctx *id_ctx;
83 : struct tevent_req *req;
84 : bool can_retry;
85 0 : bool reinit = false;
86 : errno_t ret;
87 :
88 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
89 0 : state = tevent_req_data(req, struct sdap_online_check_state);
90 :
91 0 : id_ctx = state->id_ctx;
92 :
93 0 : ret = sdap_cli_connect_recv(subreq, state, &can_retry, NULL, &srv_opts);
94 0 : talloc_zfree(subreq);
95 0 : if (ret != EOK) {
96 0 : if (can_retry == false) {
97 0 : ret = ERR_OFFLINE;
98 : }
99 :
100 0 : goto done;
101 : } else {
102 0 : if (id_ctx->srv_opts == NULL) {
103 0 : srv_opts->max_user_value = 0;
104 0 : srv_opts->max_group_value = 0;
105 0 : srv_opts->max_service_value = 0;
106 0 : srv_opts->max_sudo_value = 0;
107 0 : } else if (strcmp(srv_opts->server_id, id_ctx->srv_opts->server_id) == 0
108 0 : && srv_opts->supports_usn
109 0 : && id_ctx->srv_opts->last_usn > srv_opts->last_usn) {
110 0 : id_ctx->srv_opts->max_user_value = 0;
111 0 : id_ctx->srv_opts->max_group_value = 0;
112 0 : id_ctx->srv_opts->max_service_value = 0;
113 0 : id_ctx->srv_opts->max_sudo_value = 0;
114 0 : id_ctx->srv_opts->last_usn = srv_opts->last_usn;
115 :
116 0 : reinit = true;
117 : }
118 :
119 0 : sdap_steal_server_opts(id_ctx, &srv_opts);
120 : }
121 :
122 0 : if (reinit) {
123 0 : DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. "
124 : "Cleaning cache.\n");
125 0 : subreq = sdap_reinit_cleanup_send(state, state->be_ctx, id_ctx);
126 0 : if (subreq == NULL) {
127 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
128 : "clean up.\n");
129 : /* not fatal */
130 0 : goto done;
131 : }
132 :
133 0 : tevent_req_set_callback(subreq, sdap_online_check_reinit_done, req);
134 0 : return;
135 : }
136 :
137 0 : ret = EOK;
138 :
139 : done:
140 0 : if (ret != EOK) {
141 0 : tevent_req_error(req, ret);
142 0 : return;
143 : }
144 :
145 0 : tevent_req_done(req);
146 : }
147 :
148 0 : static void sdap_online_check_reinit_done(struct tevent_req *subreq)
149 : {
150 : struct tevent_req *req;
151 : errno_t ret;
152 :
153 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
154 :
155 0 : ret = sdap_reinit_cleanup_recv(subreq);
156 0 : talloc_zfree(subreq);
157 0 : if (ret != EOK) {
158 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
159 : "clean up [%d]: %s\n", ret, strerror(ret));
160 : /* not fatal */
161 : } else {
162 0 : DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n");
163 : }
164 :
165 0 : tevent_req_done(req);
166 0 : }
167 :
168 0 : static errno_t sdap_online_check_recv(struct tevent_req *req)
169 : {
170 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
171 :
172 0 : return EOK;
173 : }
174 :
175 : struct sdap_online_check_handler_state {
176 : struct dp_reply_std reply;
177 : };
178 :
179 : static void sdap_online_check_handler_done(struct tevent_req *subreq);
180 :
181 : struct tevent_req *
182 0 : sdap_online_check_handler_send(TALLOC_CTX *mem_ctx,
183 : struct sdap_id_ctx *id_ctx,
184 : void *data,
185 : struct dp_req_params *params)
186 : {
187 : struct sdap_online_check_handler_state *state;
188 : struct tevent_req *subreq;
189 : struct tevent_req *req;
190 : errno_t ret;
191 :
192 0 : req = tevent_req_create(mem_ctx, &state,
193 : struct sdap_online_check_handler_state);
194 0 : if (req == NULL) {
195 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
196 0 : return NULL;
197 : }
198 :
199 0 : subreq = sdap_online_check_send(state, id_ctx);
200 0 : if (subreq == NULL) {
201 0 : ret = ENOMEM;
202 0 : goto immediately;
203 : }
204 :
205 0 : tevent_req_set_callback(subreq, sdap_online_check_handler_done, req);
206 :
207 0 : return req;
208 :
209 : immediately:
210 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
211 :
212 : /* TODO For backward compatibility we always return EOK to DP now. */
213 0 : tevent_req_done(req);
214 0 : tevent_req_post(req, params->ev);
215 :
216 0 : return req;
217 : }
218 :
219 0 : static void sdap_online_check_handler_done(struct tevent_req *subreq)
220 : {
221 : struct sdap_online_check_handler_state *state;
222 : struct tevent_req *req;
223 : errno_t ret;
224 :
225 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
226 0 : state = tevent_req_data(req, struct sdap_online_check_handler_state);
227 :
228 0 : ret = sdap_online_check_recv(subreq);
229 0 : talloc_zfree(subreq);
230 :
231 : /* TODO For backward compatibility we always return EOK to DP now. */
232 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
233 0 : tevent_req_done(req);
234 0 : }
235 :
236 0 : errno_t sdap_online_check_handler_recv(TALLOC_CTX *mem_ctx,
237 : struct tevent_req *req,
238 : struct dp_reply_std *data)
239 : {
240 0 : struct sdap_online_check_handler_state *state = NULL;
241 :
242 0 : state = tevent_req_data(req, struct sdap_online_check_handler_state);
243 :
244 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
245 :
246 0 : *data = state->reply;
247 :
248 0 : return EOK;
249 : }
|