Branch data Line data Source code
1 : : /*
2 : : SSSD
3 : :
4 : : ID-mapping library
5 : :
6 : : Authors:
7 : : Sumit Bose <sbose@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 <string.h>
26 : : #include <stdio.h>
27 : : #include <errno.h>
28 : :
29 : : #include "lib/idmap/sss_idmap.h"
30 : : #include "lib/idmap/sss_idmap_private.h"
31 : :
32 : : #define SID_FMT "%s-%d"
33 : : #define SID_STR_MAX_LEN 1024
34 : :
35 : : struct idmap_domain_info {
36 : : char *name;
37 : : char *sid;
38 : : struct sss_idmap_range *range;
39 : : struct idmap_domain_info *next;
40 : : };
41 : :
42 : 1 : static void *default_alloc(size_t size, void *pvt)
43 : : {
44 : 1 : return malloc(size);
45 : : }
46 : :
47 : 1 : static void default_free(void *ptr, void *pvt)
48 : : {
49 : 1 : free(ptr);
50 : 1 : }
51 : :
52 : 14 : static char *idmap_strdup(struct sss_idmap_ctx *ctx, const char *str)
53 : : {
54 : 14 : char *new = NULL;
55 : : size_t len;
56 : :
57 [ + - ][ + - ]: 14 : CHECK_IDMAP_CTX(ctx, NULL);
[ + - ]
58 : :
59 : 14 : len = strlen(str) + 1;
60 : :
61 : 14 : new = ctx->alloc_func(len, ctx->alloc_pvt);
62 [ + - ]: 14 : if (new == NULL) {
63 : : return NULL;
64 : : }
65 : :
66 : 14 : memcpy(new, str, len);
67 : :
68 : 14 : return new;
69 : : }
70 : :
71 : 7 : static struct sss_idmap_range *idmap_range_dup(struct sss_idmap_ctx *ctx,
72 : : struct sss_idmap_range *range)
73 : : {
74 : 7 : struct sss_idmap_range *new = NULL;
75 : :
76 [ + - ][ + - ]: 7 : CHECK_IDMAP_CTX(ctx, NULL);
[ + - ]
77 : :
78 : :
79 : 7 : new = ctx->alloc_func(sizeof(struct sss_idmap_range), ctx->alloc_pvt);
80 [ + - ]: 7 : if (new == NULL) {
81 : : return NULL;
82 : : }
83 : :
84 : 7 : memset(new, 0, sizeof(struct sss_idmap_range));
85 : :
86 : 7 : new->min = range->min;
87 : 7 : new->max = range->max;
88 : :
89 : 7 : return new;
90 : : }
91 : :
92 : : static bool id_is_in_range(uint32_t id, struct sss_idmap_range *range,
93 : : uint32_t *rid)
94 : : {
95 [ + - ]: 6 : if (id == 0 || range == NULL) {
96 : : return false;
97 : : }
98 : :
99 [ + - ][ + + ]: 6 : if (id >= range->min && id <= range->max) {
100 : : if (rid != NULL) {
101 : 3 : *rid = id - range->min;
102 : : }
103 : :
104 : : return true;
105 : : }
106 : :
107 : : return false;
108 : : }
109 : :
110 : 0 : const char *idmap_error_string(enum idmap_error_code err)
111 : : {
112 [ # # # # : 0 : switch (err) {
# # # # #
# ]
113 : : case IDMAP_SUCCESS:
114 : : return "IDMAP operation successful";
115 : : break;
116 : : case IDMAP_NOT_IMPLEMENTED:
117 : 0 : return "IDMAP Function is not yet implemented";
118 : : break;
119 : : case IDMAP_ERROR:
120 : 0 : return "IDMAP general error";
121 : : break;
122 : : case IDMAP_OUT_OF_MEMORY:
123 : 0 : return "IDMAP operation ran out of memory";
124 : : break;
125 : : case IDMAP_NO_DOMAIN:
126 : 0 : return "IDMAP domain not found";
127 : : break;
128 : : case IDMAP_CONTEXT_INVALID:
129 : 0 : return "IDMAP context is invalid";
130 : : break;
131 : : case IDMAP_SID_INVALID:
132 : 0 : return "IDMAP SID is invalid";
133 : : break;
134 : : case IDMAP_SID_UNKNOWN:
135 : 0 : return "IDMAP SID not found";
136 : : break;
137 : : case IDMAP_NO_RANGE:
138 : 0 : return "IDMAP range not found";
139 : : default:
140 : 0 : return "IDMAP unknown error code";
141 : : }
142 : : }
143 : :
144 : 16 : bool is_domain_sid(const char *sid)
145 : : {
146 : : const char *p;
147 : : long long a;
148 : : char *endptr;
149 : : size_t c;
150 : :
151 [ + + ][ + + ]: 16 : if (sid == NULL || strncmp(sid, DOM_SID_PREFIX, DOM_SID_PREFIX_LEN) != 0) {
152 : : return false;
153 : : }
154 : :
155 : 13 : p = sid + DOM_SID_PREFIX_LEN;
156 : 13 : c = 0;
157 : :
158 : : do {
159 : 33 : errno = 0;
160 : 33 : a = strtoull(p, &endptr, 10);
161 [ + - ][ + + ]: 33 : if (errno != 0 || a > UINT32_MAX) {
162 : : return false;
163 : : }
164 : :
165 [ + + ]: 32 : if (*endptr == '-') {
166 : 21 : p = endptr + 1;
167 [ + + ]: 11 : } else if (*endptr != '\0') {
168 : : return false;
169 : : }
170 : 30 : c++;
171 [ + + ][ + + ]: 30 : } while(c < 3 && *endptr != '\0');
172 : :
173 [ + + ][ + + ]: 16 : if (c != 3 || *endptr != '\0') {
174 : : return false;
175 : : }
176 : :
177 : : return true;
178 : : }
179 : :
180 : 19 : enum idmap_error_code sss_idmap_init(idmap_alloc_func *alloc_func,
181 : : void *alloc_pvt,
182 : : idmap_free_func *free_func,
183 : : struct sss_idmap_ctx **_ctx)
184 : : {
185 : : struct sss_idmap_ctx *ctx;
186 : :
187 [ + + ]: 19 : if (alloc_func == NULL) {
188 : 1 : alloc_func = default_alloc;
189 : : }
190 : :
191 : 19 : ctx = alloc_func(sizeof(struct sss_idmap_ctx), alloc_pvt);
192 [ + - ]: 19 : if (ctx == NULL) {
193 : : return IDMAP_OUT_OF_MEMORY;
194 : : }
195 : 19 : memset(ctx, 0, sizeof(struct sss_idmap_ctx));
196 : :
197 : 19 : ctx->alloc_func = alloc_func;
198 : 19 : ctx->alloc_pvt = alloc_pvt;
199 [ + + ]: 19 : ctx->free_func = (free_func == NULL) ? default_free : free_func;
200 : :
201 : 19 : *_ctx = ctx;
202 : :
203 : 19 : return IDMAP_SUCCESS;
204 : : }
205 : :
206 : 19 : enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx)
207 : : {
208 : : struct idmap_domain_info *dom;
209 : : struct idmap_domain_info *next;
210 : :
211 [ + - ][ + - ]: 19 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
212 : :
213 : 19 : next = ctx->idmap_domain_info;
214 [ + + ]: 26 : while (next) {
215 : 7 : dom = next;
216 : 7 : next = dom->next;
217 : 7 : ctx->free_func(dom->range, ctx->alloc_pvt);
218 : 7 : ctx->free_func(dom->name, ctx->alloc_pvt);
219 : 7 : ctx->free_func(dom->sid, ctx->alloc_pvt);
220 : 7 : ctx->free_func(dom, ctx->alloc_pvt);
221 : : }
222 : :
223 : 19 : ctx->free_func(ctx, ctx->alloc_pvt);
224 : :
225 : 19 : return IDMAP_SUCCESS;
226 : : }
227 : :
228 : 7 : enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
229 : : const char *domain_name,
230 : : const char *domain_sid,
231 : : struct sss_idmap_range *range)
232 : : {
233 : 7 : struct idmap_domain_info *dom = NULL;
234 : :
235 [ + - ][ + - ]: 7 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
236 : :
237 [ + - ]: 7 : if (domain_name == NULL) {
238 : : return IDMAP_NO_DOMAIN;
239 : : }
240 : :
241 [ + - ]: 7 : if (range == NULL) {
242 : : return IDMAP_NO_RANGE;
243 : : }
244 : :
245 [ + - ]: 7 : if (!is_domain_sid(domain_sid)) {
246 : : return IDMAP_SID_INVALID;
247 : : }
248 : :
249 : 7 : dom = ctx->alloc_func(sizeof(struct idmap_domain_info), ctx->alloc_pvt);
250 [ + - ]: 7 : if (dom == NULL) {
251 : : return IDMAP_OUT_OF_MEMORY;
252 : : }
253 : 7 : memset(dom, 0, sizeof(struct idmap_domain_info));
254 : :
255 : 7 : dom->name = idmap_strdup(ctx, domain_name);
256 [ + - ]: 7 : if (dom->name == NULL) {
257 : : goto fail;
258 : : }
259 : :
260 : 7 : dom->sid = idmap_strdup(ctx, domain_sid);
261 [ + - ]: 7 : if (dom->sid == NULL) {
262 : : goto fail;
263 : : }
264 : :
265 : 7 : dom->range = idmap_range_dup(ctx, range);
266 [ + - ]: 7 : if (dom->range == NULL) {
267 : : goto fail;
268 : : }
269 : :
270 : 7 : dom->next = ctx->idmap_domain_info;
271 : 7 : ctx->idmap_domain_info = dom;
272 : :
273 : 7 : return IDMAP_SUCCESS;
274 : :
275 : : fail:
276 : 0 : ctx->free_func(dom->sid, ctx->alloc_pvt);
277 : 0 : ctx->free_func(dom->name, ctx->alloc_pvt);
278 : 0 : ctx->free_func(dom, ctx->alloc_pvt);
279 : :
280 : 7 : return IDMAP_OUT_OF_MEMORY;
281 : : }
282 : :
283 : 5 : static bool sss_idmap_sid_is_builtin(const char *sid)
284 : : {
285 [ + - ]: 5 : if (strncmp(sid, "S-1-5-32-", 9) == 0) {
286 : : return true;
287 : : }
288 : :
289 : 5 : return false;
290 : : }
291 : :
292 : 5 : enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx,
293 : : const char *sid,
294 : : uint32_t *id)
295 : : {
296 : : struct idmap_domain_info *idmap_domain_info;
297 : : size_t dom_len;
298 : : long long rid;
299 : : char *endptr;
300 : :
301 [ + - ][ + - ]: 5 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
302 : :
303 : 5 : idmap_domain_info = ctx->idmap_domain_info;
304 : :
305 [ + - ][ + - ]: 5 : if (sid && sss_idmap_sid_is_builtin(sid)) {
306 : : return IDMAP_BUILTIN_SID;
307 : : }
308 : :
309 [ + + ]: 10 : while (idmap_domain_info != NULL) {
310 : 5 : dom_len = strlen(idmap_domain_info->sid);
311 [ + - ][ + + ]: 5 : if (strlen(sid) > dom_len && sid[dom_len] == '-' &&
[ + - ]
312 : 4 : strncmp(sid, idmap_domain_info->sid, dom_len) == 0) {
313 : 4 : errno = 0;
314 : 4 : rid = strtoull(sid + dom_len + 1, &endptr, 10);
315 [ + - ][ + - ]: 4 : if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') {
[ + - ]
316 : : return IDMAP_SID_INVALID;
317 : : }
318 : :
319 [ + + ]: 4 : if (rid + idmap_domain_info->range->min >
320 : 4 : idmap_domain_info->range->max) {
321 : : return IDMAP_NO_RANGE;
322 : : }
323 : :
324 : 3 : *id = rid + idmap_domain_info->range->min;
325 : : return IDMAP_SUCCESS;
326 : : }
327 : :
328 : 1 : idmap_domain_info = idmap_domain_info->next;
329 : : }
330 : :
331 : : return IDMAP_NO_DOMAIN;
332 : : }
333 : :
334 : 6 : enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx,
335 : : uint32_t id,
336 : : char **_sid)
337 : : {
338 : : struct idmap_domain_info *idmap_domain_info;
339 : : int len;
340 : : int ret;
341 : : uint32_t rid;
342 : 6 : char *sid = NULL;
343 : :
344 [ + - ][ + - ]: 6 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
345 : :
346 : 6 : idmap_domain_info = ctx->idmap_domain_info;
347 : :
348 [ + + ]: 12 : while (idmap_domain_info != NULL) {
349 [ + + ]: 6 : if (id_is_in_range(id, idmap_domain_info->range, &rid)) {
350 : 3 : len = snprintf(NULL, 0, SID_FMT, idmap_domain_info->sid, rid);
351 [ + - ]: 3 : if (len <= 0 || len > SID_STR_MAX_LEN) {
352 : : return IDMAP_ERROR;
353 : : }
354 : :
355 : 3 : sid = ctx->alloc_func(len + 1, ctx->alloc_pvt);
356 [ + - ]: 3 : if (sid == NULL) {
357 : : return IDMAP_OUT_OF_MEMORY;
358 : : }
359 : :
360 : 3 : ret = snprintf(sid, len + 1, SID_FMT, idmap_domain_info->sid, rid);
361 [ - + ]: 3 : if (ret != len) {
362 : 0 : ctx->free_func(sid, ctx->alloc_pvt);
363 : : return IDMAP_ERROR;
364 : : }
365 : :
366 : 3 : *_sid = sid;
367 : : return IDMAP_SUCCESS;
368 : : }
369 : :
370 : 3 : idmap_domain_info = idmap_domain_info->next;
371 : : }
372 : :
373 : : return IDMAP_NO_DOMAIN;
374 : : }
375 : :
376 : 1 : enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx,
377 : : struct sss_dom_sid *dom_sid,
378 : : uint32_t *id)
379 : : {
380 : : enum idmap_error_code err;
381 : : char *sid;
382 : :
383 [ + - ][ + - ]: 1 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
384 : :
385 : 1 : err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid);
386 [ + - ]: 1 : if (err != IDMAP_SUCCESS) {
387 : : goto done;
388 : : }
389 : :
390 : 1 : err = sss_idmap_sid_to_unix(ctx, sid, id);
391 : :
392 : : done:
393 : 1 : ctx->free_func(sid, ctx->alloc_pvt);
394 : :
395 : : return err;
396 : : }
397 : :
398 : 1 : enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx,
399 : : uint8_t *bin_sid,
400 : : size_t length,
401 : : uint32_t *id)
402 : : {
403 : : enum idmap_error_code err;
404 : : char *sid;
405 : :
406 [ + - ][ + - ]: 1 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
407 : :
408 : 1 : err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid);
409 [ + - ]: 1 : if (err != IDMAP_SUCCESS) {
410 : : goto done;
411 : : }
412 : :
413 : 1 : err = sss_idmap_sid_to_unix(ctx, sid, id);
414 : :
415 : : done:
416 : 1 : ctx->free_func(sid, ctx->alloc_pvt);
417 : :
418 : : return err;
419 : : }
420 : :
421 : 2 : enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx,
422 : : uint32_t id,
423 : : struct sss_dom_sid **_dom_sid)
424 : : {
425 : : enum idmap_error_code err;
426 : 2 : char *sid = NULL;
427 : 2 : struct sss_dom_sid *dom_sid = NULL;
428 : :
429 [ + - ][ + - ]: 2 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
430 : :
431 : 2 : err = sss_idmap_unix_to_sid(ctx, id, &sid);
432 [ + + ]: 2 : if (err != IDMAP_SUCCESS) {
433 : : goto done;
434 : : }
435 : :
436 : 1 : err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid);
437 [ + - ]: 1 : if (err != IDMAP_SUCCESS) {
438 : : goto done;
439 : : }
440 : :
441 : 1 : *_dom_sid = dom_sid;
442 : 1 : err = IDMAP_SUCCESS;
443 : :
444 : : done:
445 : 2 : ctx->free_func(sid, ctx->alloc_pvt);
446 [ + + ]: 2 : if (err != IDMAP_SUCCESS) {
447 : 2 : ctx->free_func(dom_sid, ctx->alloc_pvt);
448 : : }
449 : :
450 : : return err;
451 : : }
452 : :
453 : 2 : enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx,
454 : : uint32_t id,
455 : : uint8_t **_bin_sid,
456 : : size_t *_length)
457 : : {
458 : : enum idmap_error_code err;
459 : 2 : char *sid = NULL;
460 : 2 : uint8_t *bin_sid = NULL;
461 : : size_t length;
462 : :
463 [ + - ][ + - ]: 2 : CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
[ + - ]
464 : :
465 : 2 : err = sss_idmap_unix_to_sid(ctx, id, &sid);
466 [ + + ]: 2 : if (err != IDMAP_SUCCESS) {
467 : : goto done;
468 : : }
469 : :
470 : 1 : err = sss_idmap_sid_to_bin_sid(ctx, sid, &bin_sid, &length);
471 [ + - ]: 1 : if (err != IDMAP_SUCCESS) {
472 : : goto done;
473 : : }
474 : :
475 : 1 : *_bin_sid = bin_sid;
476 : 1 : *_length = length;
477 : 1 : err = IDMAP_SUCCESS;
478 : :
479 : : done:
480 : 2 : ctx->free_func(sid, ctx->alloc_pvt);
481 [ + + ]: 2 : if (err != IDMAP_SUCCESS) {
482 : 2 : ctx->free_func(bin_sid, ctx->alloc_pvt);
483 : : }
484 : :
485 : : return err;
486 : :
487 : : }
|