Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Sumit Bose <sbose@redhat.com>
6 :
7 : Copyright (C) 2013 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 :
24 : #include "util/util.h"
25 : #include "providers/ldap/sdap_idmap.h"
26 : #include "providers/ipa/ipa_common.h"
27 : #include "util/util_sss_idmap.h"
28 :
29 1 : static errno_t ipa_idmap_check_posix_child(struct sdap_idmap_ctx *idmap_ctx,
30 : const char *dom_name,
31 : const char *dom_sid_str,
32 : size_t range_count,
33 : struct range_info **range_list)
34 : {
35 : bool has_algorithmic_mapping;
36 : enum idmap_error_code err;
37 : struct sss_domain_info *dom;
38 : struct sss_domain_info *forest_root;
39 : size_t c;
40 : struct sss_idmap_range range;
41 : struct range_info *r;
42 : char *range_id;
43 : TALLOC_CTX *tmp_ctx;
44 1 : bool found = false;
45 : int ret;
46 :
47 1 : err = sss_idmap_domain_has_algorithmic_mapping(idmap_ctx->map, dom_sid_str,
48 : &has_algorithmic_mapping);
49 1 : if (err == IDMAP_SUCCESS) {
50 1 : DEBUG(SSSDBG_TRACE_ALL,
51 : "Idmap of domain [%s] already known, nothing to do.\n",
52 : dom_sid_str);
53 1 : return EOK;
54 : } else {
55 0 : err = sss_idmap_domain_by_name_has_algorithmic_mapping(idmap_ctx->map,
56 : dom_name,
57 : &has_algorithmic_mapping);
58 0 : if (err == IDMAP_SUCCESS) {
59 0 : DEBUG(SSSDBG_TRACE_ALL,
60 : "Idmap of domain [%s] already known, nothing to do.\n",
61 : dom_sid_str);
62 0 : return EOK;
63 : }
64 : }
65 0 : DEBUG(SSSDBG_TRACE_ALL, "Trying to add idmap for domain [%s].\n",
66 : dom_sid_str);
67 :
68 0 : if (err != IDMAP_SID_UNKNOWN && err != IDMAP_NAME_UNKNOWN) {
69 0 : DEBUG(SSSDBG_OP_FAILURE,
70 : "sss_idmap_domain_has_algorithmic_mapping failed.\n");
71 0 : return EINVAL;
72 : }
73 :
74 0 : dom = find_domain_by_sid(idmap_ctx->id_ctx->be->domain, dom_sid_str);
75 0 : if (dom == NULL) {
76 0 : DEBUG(SSSDBG_OP_FAILURE,
77 : "find_domain_by_sid failed with SID [%s].\n", dom_sid_str);
78 0 : return EINVAL;
79 : }
80 :
81 0 : if (dom->forest == NULL) {
82 0 : DEBUG(SSSDBG_MINOR_FAILURE, "No forest available for domain [%s].\n",
83 : dom_sid_str);
84 0 : return EINVAL;
85 : }
86 :
87 0 : forest_root = find_domain_by_name(idmap_ctx->id_ctx->be->domain,
88 0 : dom->forest, true);
89 0 : if (forest_root == NULL) {
90 0 : DEBUG(SSSDBG_OP_FAILURE,
91 : "find_domain_by_name failed to find forest root [%s].\n",
92 : dom->forest);
93 0 : return ENOENT;
94 : }
95 :
96 0 : if (forest_root->domain_id == NULL) {
97 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Forest root [%s] does not have a SID.\n",
98 : dom->forest);
99 0 : return EINVAL;
100 : }
101 :
102 0 : tmp_ctx = talloc_new(NULL);
103 0 : if (tmp_ctx == NULL) {
104 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
105 0 : return ENOMEM;
106 : }
107 :
108 0 : for (c = 0; c < range_count; c++) {
109 0 : r = range_list[c];
110 0 : if (r->trusted_dom_sid != NULL
111 0 : && strcmp(r->trusted_dom_sid, forest_root->domain_id) == 0) {
112 :
113 0 : if (r->range_type == NULL
114 0 : || strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) != 0) {
115 0 : DEBUG(SSSDBG_MINOR_FAILURE,
116 : "Forest root does not have range type [%s].\n",
117 : IPA_RANGE_AD_TRUST_POSIX);
118 0 : ret = EINVAL;
119 0 : goto done;
120 : }
121 :
122 0 : range.min = r->base_id;
123 0 : range.max = r->base_id + r->id_range_size -1;
124 0 : range_id = talloc_asprintf(tmp_ctx, "%s-%s", dom_sid_str, r->name);
125 0 : if (range_id == NULL) {
126 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
127 0 : ret = ENOMEM;
128 0 : goto done;
129 : }
130 :
131 0 : err = sss_idmap_add_domain_ex(idmap_ctx->map, dom_name, dom_sid_str,
132 : &range, range_id, 0, true);
133 0 : if (err != IDMAP_SUCCESS && err != IDMAP_COLLISION) {
134 0 : DEBUG(SSSDBG_CRIT_FAILURE,
135 : "Could not add range [%s] to ID map\n", range_id);
136 0 : ret = EIO;
137 0 : goto done;
138 : }
139 :
140 0 : found = true;
141 : }
142 : }
143 :
144 0 : if (!found) {
145 0 : DEBUG(SSSDBG_MINOR_FAILURE, "No idrange found for forest root [%s].\n",
146 : forest_root->domain_id);
147 0 : ret = ENOENT;
148 0 : goto done;
149 : }
150 :
151 0 : ret = EOK;
152 :
153 : done:
154 0 : talloc_free(tmp_ctx);
155 :
156 0 : return ret;
157 : }
158 :
159 5 : errno_t get_idmap_data_from_range(struct range_info *r, char *domain_name,
160 : char **_name, char **_sid, uint32_t *_rid,
161 : struct sss_idmap_range *_range,
162 : bool *_external_mapping)
163 : {
164 5 : if (r->range_type == NULL) {
165 : /* Older IPA servers might not have the range_type attribute, but
166 : * only support local ranges and trusts with algorithmic mapping. */
167 :
168 1 : if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) {
169 : /* local IPA domain */
170 1 : *_rid = 0;
171 1 : *_external_mapping = true;
172 1 : *_name = domain_name;
173 1 : *_sid = NULL;
174 0 : } else if (r->trusted_dom_sid != NULL
175 0 : && r->secondary_base_rid == 0) {
176 : /* trusted domain */
177 0 : *_rid = r->base_rid;
178 0 : *_external_mapping = false;
179 0 : *_name = r->trusted_dom_sid;
180 0 : *_sid = r->trusted_dom_sid;
181 : } else {
182 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Cannot determine range type, " \
183 : "for id range [%s].\n",
184 : r->name);
185 0 : return EINVAL;
186 : }
187 : } else {
188 4 : if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) {
189 1 : *_rid = 0;
190 1 : *_external_mapping = true;
191 1 : *_name = domain_name;
192 1 : *_sid = NULL;
193 3 : } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) {
194 0 : *_rid = 0;
195 0 : *_external_mapping = true;
196 0 : *_name = r->trusted_dom_sid;
197 0 : *_sid = r->trusted_dom_sid;
198 3 : } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) {
199 3 : *_rid = r->base_rid;
200 3 : *_external_mapping = false;
201 3 : *_name = r->trusted_dom_sid;
202 3 : *_sid = r->trusted_dom_sid;
203 : } else {
204 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Range type [%s] of id range " \
205 : "[%s] not supported.\n", \
206 : r->range_type, r->name);
207 0 : return EINVAL;
208 : }
209 : }
210 :
211 5 : _range->min = r->base_id;
212 5 : _range->max = r->base_id + r->id_range_size -1;
213 :
214 5 : return EOK;
215 : }
216 :
217 3 : errno_t ipa_idmap_get_ranges_from_sysdb(struct sdap_idmap_ctx *idmap_ctx,
218 : const char *dom_name,
219 : const char *dom_sid_str,
220 : bool allow_collisions)
221 : {
222 : int ret;
223 : size_t range_count;
224 : struct range_info **range_list;
225 : TALLOC_CTX *tmp_ctx;
226 : size_t c;
227 : enum idmap_error_code err;
228 : struct sss_idmap_range range;
229 : uint32_t rid;
230 : bool external_mapping;
231 : char *name;
232 : char *sid;
233 :
234 3 : tmp_ctx = talloc_new(NULL);
235 3 : if (tmp_ctx == NULL) {
236 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
237 0 : return ENOMEM;
238 : }
239 :
240 3 : ret = sysdb_get_ranges(tmp_ctx, idmap_ctx->id_ctx->be->domain->sysdb,
241 : &range_count, &range_list);
242 3 : if (ret != EOK) {
243 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_ranges failed.\n");
244 0 : goto done;
245 : }
246 :
247 5 : for (c = 0; c < range_count; c++) {
248 3 : ret = get_idmap_data_from_range(range_list[c],
249 3 : idmap_ctx->id_ctx->be->domain->name,
250 : &name, &sid, &rid, &range,
251 : &external_mapping);
252 3 : if (ret != EOK) {
253 0 : DEBUG(SSSDBG_OP_FAILURE, "get_idmap_data_from_range failed for " \
254 : "id range [%s], skipping.\n",
255 : range_list[c]->name);
256 0 : continue;
257 : }
258 :
259 6 : err = sss_idmap_add_domain_ex(idmap_ctx->map, name, sid, &range,
260 3 : range_list[c]->name, rid,
261 : external_mapping);
262 3 : if (err != IDMAP_SUCCESS) {
263 2 : if (!allow_collisions || err != IDMAP_COLLISION) {
264 1 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not add range [%s] to ID map\n",
265 : range_list[c]->name);
266 1 : ret = EIO;
267 1 : goto done;
268 : }
269 : }
270 : }
271 :
272 2 : if (dom_name != NULL || dom_sid_str != NULL) {
273 1 : ret = ipa_idmap_check_posix_child(idmap_ctx, dom_name, dom_sid_str,
274 : range_count, range_list);
275 1 : if (ret != EOK) {
276 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_idmap_check_posix_child failed.\n");
277 0 : goto done;
278 : }
279 : }
280 :
281 2 : ret = EOK;
282 :
283 : done:
284 3 : talloc_free(tmp_ctx);
285 :
286 3 : return ret;
287 : }
288 :
289 0 : errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
290 : const char *dom_name,
291 : const char *dom_sid_str)
292 : {
293 0 : return ipa_idmap_get_ranges_from_sysdb(idmap_ctx, dom_name, dom_sid_str,
294 : true);
295 : }
296 :
297 1 : errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx,
298 : struct sdap_id_ctx *id_ctx,
299 : struct sdap_idmap_ctx **_idmap_ctx)
300 : {
301 : errno_t ret;
302 : TALLOC_CTX *tmp_ctx;
303 : enum idmap_error_code err;
304 1 : struct sdap_idmap_ctx *idmap_ctx = NULL;
305 :
306 1 : tmp_ctx = talloc_new(NULL);
307 1 : if (!tmp_ctx) return ENOMEM;
308 :
309 1 : idmap_ctx = talloc_zero(tmp_ctx, struct sdap_idmap_ctx);
310 1 : if (!idmap_ctx) {
311 0 : ret = ENOMEM;
312 0 : goto done;
313 : }
314 1 : idmap_ctx->id_ctx = id_ctx;
315 1 : idmap_ctx->find_new_domain = ipa_idmap_find_new_domain;
316 :
317 : /* Initialize the map */
318 1 : err = sss_idmap_init(sss_idmap_talloc, idmap_ctx,
319 : sss_idmap_talloc_free,
320 : &idmap_ctx->map);
321 1 : if (err != IDMAP_SUCCESS) {
322 0 : DEBUG(SSSDBG_CRIT_FAILURE,
323 : "Could not initialize the ID map: [%s]\n",
324 : idmap_error_string(err));
325 0 : if (err == IDMAP_OUT_OF_MEMORY) {
326 0 : ret = ENOMEM;
327 : } else {
328 0 : ret = EINVAL;
329 : }
330 0 : goto done;
331 : }
332 :
333 1 : ret = ipa_idmap_get_ranges_from_sysdb(idmap_ctx, NULL, NULL, false);
334 1 : if (ret != EOK) {
335 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_idmap_get_ranges_from_sysdb failed.\n");
336 0 : goto done;
337 : }
338 :
339 1 : *_idmap_ctx = talloc_steal(mem_ctx, idmap_ctx);
340 1 : ret = EOK;
341 :
342 : done:
343 1 : talloc_free(tmp_ctx);
344 1 : return ret;
345 : }
|