Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Identity Backend Module - Netgroup support
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2010 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 :
27 : #include "util/util.h"
28 : #include "db/sysdb.h"
29 : #include "providers/ldap/ldap_common.h"
30 : #include "providers/ldap/sdap_async.h"
31 :
32 :
33 : struct ldap_netgroup_get_state {
34 : struct tevent_context *ev;
35 : struct sdap_id_ctx *ctx;
36 : struct sdap_domain *sdom;
37 : struct sdap_id_op *op;
38 : struct sdap_id_conn_ctx *conn;
39 : struct sysdb_ctx *sysdb;
40 : struct sss_domain_info *domain;
41 :
42 : const char *name;
43 : int timeout;
44 :
45 : char *filter;
46 : const char **attrs;
47 :
48 : size_t count;
49 : struct sysdb_attrs **netgroups;
50 :
51 : int dp_error;
52 : int sdap_ret;
53 : bool noexist_delete;
54 : };
55 :
56 : static int ldap_netgroup_get_retry(struct tevent_req *req);
57 : static void ldap_netgroup_get_connect_done(struct tevent_req *subreq);
58 : static void ldap_netgroup_get_done(struct tevent_req *subreq);
59 :
60 0 : struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
61 : struct tevent_context *ev,
62 : struct sdap_id_ctx *ctx,
63 : struct sdap_domain *sdom,
64 : struct sdap_id_conn_ctx *conn,
65 : const char *name,
66 : bool noexist_delete)
67 : {
68 : struct tevent_req *req;
69 : struct ldap_netgroup_get_state *state;
70 : char *clean_name;
71 : int ret;
72 :
73 0 : req = tevent_req_create(memctx, &state, struct ldap_netgroup_get_state);
74 0 : if (!req) return NULL;
75 :
76 0 : state->ev = ev;
77 0 : state->ctx = ctx;
78 0 : state->sdom = sdom;
79 0 : state->conn = conn;
80 0 : state->dp_error = DP_ERR_FATAL;
81 0 : state->noexist_delete = noexist_delete;
82 :
83 0 : state->op = sdap_id_op_create(state, state->conn->conn_cache);
84 0 : if (!state->op) {
85 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
86 0 : ret = ENOMEM;
87 0 : goto fail;
88 : }
89 :
90 0 : state->domain = sdom->dom;
91 0 : state->sysdb = sdom->dom->sysdb;
92 0 : state->name = name;
93 0 : state->timeout = dp_opt_get_int(ctx->opts->basic, SDAP_SEARCH_TIMEOUT);
94 :
95 0 : ret = sss_filter_sanitize(state, name, &clean_name);
96 0 : if (ret != EOK) {
97 0 : goto fail;
98 : }
99 :
100 0 : state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
101 0 : ctx->opts->netgroup_map[SDAP_AT_NETGROUP_NAME].name,
102 : clean_name,
103 0 : ctx->opts->netgroup_map[SDAP_OC_NETGROUP].name);
104 0 : if (!state->filter) {
105 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n");
106 0 : ret = ENOMEM;
107 0 : goto fail;
108 : }
109 0 : talloc_zfree(clean_name);
110 :
111 0 : ret = build_attrs_from_map(state, ctx->opts->netgroup_map, SDAP_OPTS_NETGROUP,
112 0 : NULL, &state->attrs, NULL);
113 0 : if (ret != EOK) goto fail;
114 :
115 0 : ret = ldap_netgroup_get_retry(req);
116 0 : if (ret != EOK) {
117 0 : goto fail;
118 : }
119 :
120 0 : return req;
121 :
122 : fail:
123 0 : tevent_req_error(req, ret);
124 0 : tevent_req_post(req, ev);
125 0 : return req;
126 : }
127 :
128 0 : static int ldap_netgroup_get_retry(struct tevent_req *req)
129 : {
130 0 : struct ldap_netgroup_get_state *state = tevent_req_data(req,
131 : struct ldap_netgroup_get_state);
132 : struct tevent_req *subreq;
133 0 : int ret = EOK;
134 :
135 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
136 0 : if (!subreq) {
137 0 : return ret;
138 : }
139 :
140 0 : tevent_req_set_callback(subreq, ldap_netgroup_get_connect_done, req);
141 0 : return EOK;
142 : }
143 :
144 0 : static void ldap_netgroup_get_connect_done(struct tevent_req *subreq)
145 : {
146 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
147 : struct tevent_req);
148 0 : struct ldap_netgroup_get_state *state = tevent_req_data(req,
149 : struct ldap_netgroup_get_state);
150 0 : int dp_error = DP_ERR_FATAL;
151 : int ret;
152 :
153 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
154 0 : talloc_zfree(subreq);
155 :
156 0 : if (ret != EOK) {
157 0 : state->dp_error = dp_error;
158 0 : tevent_req_error(req, ret);
159 0 : return;
160 : }
161 :
162 0 : subreq = sdap_get_netgroups_send(state, state->ev,
163 : state->domain, state->sysdb,
164 0 : state->ctx->opts,
165 0 : state->sdom->netgroup_search_bases,
166 : sdap_id_op_handle(state->op),
167 0 : state->attrs, state->filter,
168 : state->timeout);
169 0 : if (!subreq) {
170 0 : tevent_req_error(req, ENOMEM);
171 0 : return;
172 : }
173 0 : tevent_req_set_callback(subreq, ldap_netgroup_get_done, req);
174 :
175 0 : return;
176 : }
177 :
178 0 : static void ldap_netgroup_get_done(struct tevent_req *subreq)
179 : {
180 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
181 : struct tevent_req);
182 0 : struct ldap_netgroup_get_state *state = tevent_req_data(req,
183 : struct ldap_netgroup_get_state);
184 0 : int dp_error = DP_ERR_FATAL;
185 : int ret;
186 :
187 0 : ret = sdap_get_netgroups_recv(subreq, state, NULL, &state->count,
188 : &state->netgroups);
189 0 : talloc_zfree(subreq);
190 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
191 :
192 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
193 : /* retry */
194 0 : ret = ldap_netgroup_get_retry(req);
195 0 : if (ret != EOK) {
196 0 : tevent_req_error(req, ret);
197 0 : return;
198 : }
199 :
200 0 : return;
201 : }
202 0 : state->sdap_ret = ret;
203 :
204 0 : if (ret && ret != ENOENT) {
205 0 : state->dp_error = dp_error;
206 0 : tevent_req_error(req, ret);
207 0 : return;
208 : }
209 :
210 0 : if (ret == EOK && state->count > 1) {
211 0 : DEBUG(SSSDBG_CRIT_FAILURE,
212 : "Found more than one netgroup with the name [%s].\n",
213 : state->name);
214 0 : tevent_req_error(req, EINVAL);
215 0 : return;
216 : }
217 :
218 0 : if (ret == ENOENT && state->noexist_delete == true) {
219 0 : ret = sysdb_delete_netgroup(state->domain, state->name);
220 0 : if (ret != EOK && ret != ENOENT) {
221 0 : tevent_req_error(req, ret);
222 0 : return;
223 : }
224 : }
225 :
226 0 : state->dp_error = DP_ERR_OK;
227 0 : tevent_req_done(req);
228 0 : return;
229 : }
230 :
231 0 : int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
232 : {
233 0 : struct ldap_netgroup_get_state *state = tevent_req_data(req,
234 : struct ldap_netgroup_get_state);
235 :
236 0 : if (dp_error_out) {
237 0 : *dp_error_out = state->dp_error;
238 : }
239 :
240 0 : if (sdap_ret) {
241 0 : *sdap_ret = state->sdap_ret;
242 : }
243 :
244 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
245 :
246 0 : return EOK;
247 : }
|