Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2011 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 <string.h>
23 : #include <tevent.h>
24 :
25 : #include "providers/backend.h"
26 : #include "providers/ldap/ldap_common.h"
27 : #include "providers/ldap/sdap.h"
28 : #include "providers/ldap/sdap_async.h"
29 : #include "providers/ldap/sdap_sudo.h"
30 : #include "db/sysdb_sudo.h"
31 :
32 : struct sdap_sudo_handler_state {
33 : uint32_t type;
34 : struct dp_reply_std reply;
35 : };
36 :
37 : static void sdap_sudo_handler_done(struct tevent_req *subreq);
38 :
39 : static struct tevent_req *
40 0 : sdap_sudo_handler_send(TALLOC_CTX *mem_ctx,
41 : struct sdap_sudo_ctx *sudo_ctx,
42 : struct dp_sudo_data *data,
43 : struct dp_req_params *params)
44 : {
45 : struct sdap_sudo_handler_state *state;
46 : struct tevent_req *subreq;
47 : struct tevent_req *req;
48 : errno_t ret;
49 :
50 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_handler_state);
51 0 : if (req == NULL) {
52 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
53 0 : return NULL;
54 : }
55 :
56 0 : state->type = data->type;
57 :
58 0 : switch (data->type) {
59 : case BE_REQ_SUDO_FULL:
60 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
61 0 : subreq = sdap_sudo_full_refresh_send(state, sudo_ctx);
62 0 : break;
63 : case BE_REQ_SUDO_RULES:
64 0 : DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
65 0 : subreq = sdap_sudo_rules_refresh_send(state, sudo_ctx, data->rules);
66 0 : break;
67 : default:
68 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", data->type);
69 0 : ret = EINVAL;
70 0 : goto immediately;
71 : }
72 :
73 0 : if (subreq == NULL) {
74 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n", data->type);
75 0 : ret = ENOMEM;
76 0 : goto immediately;
77 : }
78 :
79 0 : tevent_req_set_callback(subreq, sdap_sudo_handler_done, req);
80 :
81 0 : return req;
82 :
83 : immediately:
84 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
85 :
86 : /* TODO For backward compatibility we always return EOK to DP now. */
87 0 : tevent_req_done(req);
88 0 : tevent_req_post(req, params->ev);
89 :
90 0 : return req;
91 : }
92 :
93 0 : static void sdap_sudo_handler_done(struct tevent_req *subreq)
94 : {
95 : struct sdap_sudo_handler_state *state;
96 : struct tevent_req *req;
97 : int dp_error;
98 : bool deleted;
99 : errno_t ret;
100 :
101 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
102 0 : state = tevent_req_data(req, struct sdap_sudo_handler_state);
103 :
104 0 : switch (state->type) {
105 : case BE_REQ_SUDO_FULL:
106 0 : ret = sdap_sudo_full_refresh_recv(subreq, &dp_error);
107 0 : talloc_zfree(subreq);
108 0 : break;
109 : case BE_REQ_SUDO_RULES:
110 0 : ret = sdap_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
111 0 : talloc_zfree(subreq);
112 0 : if (ret == EOK && deleted == true) {
113 0 : ret = ENOENT;
114 : }
115 0 : break;
116 : default:
117 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type);
118 0 : dp_error = DP_ERR_FATAL;
119 0 : ret = ERR_INTERNAL;
120 0 : break;
121 : }
122 :
123 : /* TODO For backward compatibility we always return EOK to DP now. */
124 0 : dp_reply_std_set(&state->reply, dp_error, ret, NULL);
125 0 : tevent_req_done(req);
126 0 : }
127 :
128 : static errno_t
129 0 : sdap_sudo_handler_recv(TALLOC_CTX *mem_ctx,
130 : struct tevent_req *req,
131 : struct dp_reply_std *data)
132 : {
133 0 : struct sdap_sudo_handler_state *state = NULL;
134 :
135 0 : state = tevent_req_data(req, struct sdap_sudo_handler_state);
136 :
137 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
138 :
139 0 : *data = state->reply;
140 :
141 0 : return EOK;
142 : }
143 :
144 0 : static void sdap_sudo_online_cb(void *pvt)
145 : {
146 : struct sdap_sudo_ctx *sudo_ctx;
147 :
148 0 : sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
149 0 : if (sudo_ctx == NULL) {
150 0 : DEBUG(SSSDBG_FATAL_FAILURE, "BUG: sudo_ctx is NULL\n");
151 0 : return;
152 : }
153 :
154 0 : DEBUG(SSSDBG_TRACE_FUNC, "We are back online. SUDO host information will "
155 : "be renewed on next refresh.\n");
156 0 : sudo_ctx->run_hostinfo = true;
157 : }
158 :
159 0 : errno_t sdap_sudo_init(TALLOC_CTX *mem_ctx,
160 : struct be_ctx *be_ctx,
161 : struct sdap_id_ctx *id_ctx,
162 : struct dp_method *dp_methods)
163 : {
164 : struct sdap_sudo_ctx *sudo_ctx;
165 : int ret;
166 :
167 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing sudo LDAP back end\n");
168 :
169 0 : sudo_ctx = talloc_zero(mem_ctx, struct sdap_sudo_ctx);
170 0 : if (sudo_ctx == NULL) {
171 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n");
172 0 : return ENOMEM;
173 : }
174 :
175 0 : sudo_ctx->id_ctx = id_ctx;
176 :
177 0 : ret = ldap_get_sudo_options(be_ctx->cdb, be_ctx->conf_path, id_ctx->opts,
178 : &sudo_ctx->use_host_filter,
179 : &sudo_ctx->include_regexp,
180 : &sudo_ctx->include_netgroups);
181 0 : if (ret != EOK) {
182 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot get SUDO options [%d]: %s\n",
183 : ret, sss_strerror(ret));
184 0 : goto done;
185 : }
186 :
187 0 : if (sudo_ctx->use_host_filter) {
188 0 : ret = be_add_online_cb(sudo_ctx, be_ctx, sdap_sudo_online_cb,
189 : sudo_ctx, NULL);
190 0 : if (ret != EOK) {
191 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to install online callback "
192 : "[%d]: %s\n", ret, sss_strerror(ret));
193 0 : goto done;
194 : }
195 :
196 : /* Obtain hostinfo with the first refresh. */
197 0 : sudo_ctx->run_hostinfo = true;
198 : }
199 :
200 0 : ret = sdap_sudo_ptask_setup(be_ctx, sudo_ctx);
201 0 : if (ret != EOK) {
202 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh of "
203 : "sudo rules [%d]: %s\n", ret, sss_strerror(ret));
204 : /* periodical updates will not work, but specific-rule update
205 : * is no affected by this, therefore we don't have to fail here */
206 : }
207 :
208 0 : dp_set_method(dp_methods, DPM_SUDO_HANDLER,
209 : sdap_sudo_handler_send, sdap_sudo_handler_recv, sudo_ctx,
210 : struct sdap_sudo_ctx, struct dp_sudo_data, struct dp_reply_std);
211 :
212 0 : ret = EOK;
213 :
214 : done:
215 0 : if (ret != EOK) {
216 0 : talloc_free(sudo_ctx);
217 : }
218 :
219 0 : return ret;
220 : }
|