/src/samba/libcli/security/dom_sid.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | Samba utility functions |
4 | | |
5 | | Copyright (C) Stefan (metze) Metzmacher 2002-2004 |
6 | | Copyright (C) Andrew Tridgell 1992-2004 |
7 | | Copyright (C) Jeremy Allison 1999 |
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 | | #include "replace.h" |
24 | | #include "lib/util/data_blob.h" |
25 | | #include "system/locale.h" |
26 | | #include "lib/util/debug.h" |
27 | | #include "lib/util/util.h" |
28 | | #include "librpc/gen_ndr/security.h" |
29 | | #include "dom_sid.h" |
30 | | #include "lib/util/smb_strtox.h" |
31 | | #include "lib/util/tsort.h" |
32 | | |
33 | | /***************************************************************** |
34 | | Compare the auth portion of two sids. |
35 | | *****************************************************************/ |
36 | | |
37 | | int dom_sid_compare_auth(const struct dom_sid *sid1, |
38 | | const struct dom_sid *sid2) |
39 | 3.93M | { |
40 | 3.93M | int i; |
41 | | |
42 | 3.93M | if (sid1 == sid2) { |
43 | 0 | return 0; |
44 | 0 | } |
45 | | |
46 | 3.93M | if (sid1 == NULL) { |
47 | 0 | return -1; |
48 | 0 | } |
49 | | |
50 | 3.93M | if (sid2 == NULL) { |
51 | 0 | return 1; |
52 | 0 | } |
53 | | |
54 | 3.93M | if (sid1->sid_rev_num != sid2->sid_rev_num) { |
55 | 2.46M | return NUMERIC_CMP(sid1->sid_rev_num, sid2->sid_rev_num); |
56 | 2.46M | } |
57 | | |
58 | 4.19M | for (i = 0; i < 6; i++) { |
59 | 3.94M | if (sid1->id_auth[i] != sid2->id_auth[i]) { |
60 | 1.22M | return NUMERIC_CMP(sid1->id_auth[i], sid2->id_auth[i]); |
61 | 1.22M | } |
62 | 3.94M | } |
63 | | |
64 | 249k | return 0; |
65 | 1.47M | } |
66 | | |
67 | | /***************************************************************** |
68 | | Compare two sids. |
69 | | *****************************************************************/ |
70 | | |
71 | | int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) |
72 | 4.91M | { |
73 | 4.91M | int i; |
74 | | |
75 | 4.91M | if (sid1 == sid2) { |
76 | 6.78k | return 0; |
77 | 6.78k | } |
78 | | |
79 | 4.91M | if (sid1 == NULL) { |
80 | 0 | return -1; |
81 | 0 | } |
82 | | |
83 | 4.91M | if (sid2 == NULL) { |
84 | 53.0k | return 1; |
85 | 53.0k | } |
86 | | |
87 | | /* Compare most likely different rids, first: i.e start at end */ |
88 | 4.85M | if (sid1->num_auths != sid2->num_auths) { |
89 | 888k | return NUMERIC_CMP(sid1->num_auths, sid2->num_auths); |
90 | 888k | } |
91 | 4.08M | for (i = sid1->num_auths-1; i >= 0; --i) { |
92 | 189k | if (sid1->sub_auths[i] < sid2->sub_auths[i]) { |
93 | 28.7k | return -1; |
94 | 28.7k | } |
95 | 161k | if (sid1->sub_auths[i] > sid2->sub_auths[i]) { |
96 | 46.7k | return 1; |
97 | 46.7k | } |
98 | 161k | } |
99 | | |
100 | 3.89M | return dom_sid_compare_auth(sid1, sid2); |
101 | 3.97M | } |
102 | | |
103 | | /***************************************************************** |
104 | | Compare two sids. |
105 | | *****************************************************************/ |
106 | | |
107 | | bool dom_sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2) |
108 | 4.91M | { |
109 | 4.91M | return dom_sid_compare(sid1, sid2) == 0; |
110 | 4.91M | } |
111 | | |
112 | | /***************************************************************** |
113 | | Add a rid to the end of a sid |
114 | | *****************************************************************/ |
115 | | |
116 | | bool sid_append_rid(struct dom_sid *sid, uint32_t rid) |
117 | 314k | { |
118 | 314k | if (sid->num_auths < ARRAY_SIZE(sid->sub_auths)) { |
119 | 314k | sid->sub_auths[sid->num_auths++] = rid; |
120 | 314k | return true; |
121 | 314k | } |
122 | 284 | return false; |
123 | 314k | } |
124 | | |
125 | | /* |
126 | | See if 2 SIDs are in the same domain |
127 | | this just compares the leading sub-auths |
128 | | */ |
129 | | int dom_sid_compare_domain(const struct dom_sid *sid1, |
130 | | const struct dom_sid *sid2) |
131 | 0 | { |
132 | 0 | int n, i; |
133 | |
|
134 | 0 | n = MIN(sid1->num_auths, sid2->num_auths); |
135 | |
|
136 | 0 | for (i = n-1; i >= 0; --i) { |
137 | 0 | if (sid1->sub_auths[i] < sid2->sub_auths[i]) { |
138 | 0 | return -1; |
139 | 0 | } |
140 | 0 | if (sid1->sub_auths[i] > sid2->sub_auths[i]) { |
141 | 0 | return 1; |
142 | 0 | } |
143 | 0 | } |
144 | | |
145 | 0 | return dom_sid_compare_auth(sid1, sid2); |
146 | 0 | } |
147 | | |
148 | | /***************************************************************** |
149 | | Convert a string to a SID. Returns True on success, False on fail. |
150 | | Return the first character not parsed in endp. |
151 | | *****************************************************************/ |
152 | 348k | #define AUTHORITY_MASK (~(0xffffffffffffULL)) |
153 | | |
154 | | bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout, |
155 | | const char **endp) |
156 | 203k | { |
157 | 203k | const char *p; |
158 | 203k | char *q = NULL; |
159 | 203k | char *end = NULL; |
160 | 203k | uint64_t conv; |
161 | 203k | int error = 0; |
162 | | |
163 | 203k | *sidout = (struct dom_sid) {}; |
164 | | |
165 | 203k | if ((sidstr[0] != 'S' && sidstr[0] != 's') || sidstr[1] != '-') { |
166 | 24.7k | DBG_INFO("'%s' is not a SID\n", sidstr); |
167 | 24.7k | return false; |
168 | 24.7k | } |
169 | | |
170 | | /* Get the revision number. */ |
171 | 179k | p = sidstr + 2; |
172 | | |
173 | 179k | if (!isdigit((unsigned char)*p)) { |
174 | 689 | goto format_error; |
175 | 689 | } |
176 | | |
177 | 178k | conv = smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD); |
178 | 178k | if (error != 0 || (*q != '-') || conv > UINT8_MAX || q - p > 4) { |
179 | 3.46k | goto format_error; |
180 | 3.46k | } |
181 | 175k | sidout->sid_rev_num = (uint8_t) conv; |
182 | 175k | q++; |
183 | | |
184 | 175k | if (!isdigit((unsigned char)*q)) { |
185 | 718 | goto format_error; |
186 | 718 | } |
187 | 203k | while (q[0] == '0' && isdigit((unsigned char)q[1])) { |
188 | | /* |
189 | | * strtoull will think this is octal, which is not how SIDs |
190 | | * work! So let's walk along until there are no leading zeros |
191 | | * (or a single zero). |
192 | | */ |
193 | 29.2k | q++; |
194 | 29.2k | } |
195 | | |
196 | | /* get identauth */ |
197 | 174k | conv = smb_strtoull(q, &end, 0, &error, SMB_STR_STANDARD); |
198 | 174k | if (conv & AUTHORITY_MASK || error != 0) { |
199 | 700 | goto format_error; |
200 | 700 | } |
201 | 173k | if (conv >= (1ULL << 48) || end - q > 15) { |
202 | | /* |
203 | | * This identauth looks like a big number, but resolves to a |
204 | | * small number after rounding. |
205 | | */ |
206 | 418 | goto format_error; |
207 | 418 | } |
208 | | |
209 | | /* NOTE - the conv value is in big-endian format. */ |
210 | 173k | sidout->id_auth[0] = (conv & 0xff0000000000ULL) >> 40; |
211 | 173k | sidout->id_auth[1] = (conv & 0x00ff00000000ULL) >> 32; |
212 | 173k | sidout->id_auth[2] = (conv & 0x0000ff000000ULL) >> 24; |
213 | 173k | sidout->id_auth[3] = (conv & 0x000000ff0000ULL) >> 16; |
214 | 173k | sidout->id_auth[4] = (conv & 0x00000000ff00ULL) >> 8; |
215 | 173k | sidout->id_auth[5] = (conv & 0x0000000000ffULL); |
216 | | |
217 | 173k | sidout->num_auths = 0; |
218 | 173k | q = end; |
219 | 173k | if (*q != '-') { |
220 | | /* Just id_auth, no subauths */ |
221 | 24.5k | goto done; |
222 | 24.5k | } |
223 | | |
224 | 148k | q++; |
225 | | |
226 | 277k | while (true) { |
227 | 277k | if (!isdigit((unsigned char)*q)) { |
228 | 878 | goto format_error; |
229 | 878 | } |
230 | 287k | while (q[0] == '0' && isdigit((unsigned char)q[1])) { |
231 | | /* |
232 | | * strtoull will think this is octal, which is not how |
233 | | * SIDs work! So let's walk along until there are no |
234 | | * leading zeros (or a single zero). |
235 | | */ |
236 | 10.1k | q++; |
237 | 10.1k | } |
238 | 276k | conv = smb_strtoull(q, &end, 0, &error, SMB_STR_STANDARD); |
239 | 276k | if (conv > UINT32_MAX || error != 0 || end - q > 12) { |
240 | | /* |
241 | | * This sub-auth is greater than 4294967295, |
242 | | * and hence invalid. Windows will treat it as |
243 | | * 4294967295, while we prefer to refuse (old |
244 | | * versions of Samba will wrap, arriving at |
245 | | * another number altogether). |
246 | | */ |
247 | 1.21k | DBG_NOTICE("bad sub-auth in %s\n", sidstr); |
248 | 1.21k | goto format_error; |
249 | 1.21k | } |
250 | | |
251 | 275k | if (!sid_append_rid(sidout, conv)) { |
252 | 284 | DEBUG(3, ("Too many sid auths in %s\n", sidstr)); |
253 | 284 | return false; |
254 | 284 | } |
255 | | |
256 | 275k | q = end; |
257 | 275k | if (*q != '-') { |
258 | 146k | break; |
259 | 146k | } |
260 | 129k | q += 1; |
261 | 129k | } |
262 | 170k | done: |
263 | 170k | if (endp != NULL) { |
264 | 47.7k | *endp = q; |
265 | 47.7k | } |
266 | 170k | return true; |
267 | | |
268 | 8.07k | format_error: |
269 | 8.07k | DEBUG(3, ("string_to_sid: SID %s is not in a valid format\n", sidstr)); |
270 | 8.07k | return false; |
271 | 148k | } |
272 | | |
273 | | bool string_to_sid(struct dom_sid *sidout, const char *sidstr) |
274 | 6 | { |
275 | 6 | return dom_sid_parse(sidstr, sidout); |
276 | 6 | } |
277 | | |
278 | | bool dom_sid_parse(const char *sidstr, struct dom_sid *ret) |
279 | 123k | { |
280 | 123k | return dom_sid_parse_endp(sidstr, ret, NULL); |
281 | 123k | } |
282 | | |
283 | | /* |
284 | | convert a string to a dom_sid, returning a talloc'd dom_sid |
285 | | */ |
286 | | struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr) |
287 | 0 | { |
288 | 0 | struct dom_sid *ret; |
289 | 0 | ret = talloc(mem_ctx, struct dom_sid); |
290 | 0 | if (!ret) { |
291 | 0 | return NULL; |
292 | 0 | } |
293 | 0 | if (!dom_sid_parse(sidstr, ret)) { |
294 | 0 | talloc_free(ret); |
295 | 0 | return NULL; |
296 | 0 | } |
297 | | |
298 | 0 | return ret; |
299 | 0 | } |
300 | | |
301 | | /* |
302 | | convert a string to a dom_sid, returning a talloc'd dom_sid |
303 | | */ |
304 | | struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid) |
305 | 0 | { |
306 | 0 | char p[sid->length+1]; |
307 | 0 | memcpy(p, sid->data, sid->length); |
308 | 0 | p[sid->length] = '\0'; |
309 | 0 | return dom_sid_parse_talloc(mem_ctx, p); |
310 | 0 | } |
311 | | |
312 | | /* |
313 | | copy a dom_sid structure |
314 | | */ |
315 | | struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid) |
316 | 37.6k | { |
317 | 37.6k | struct dom_sid *ret; |
318 | | |
319 | 37.6k | if (!dom_sid) { |
320 | 0 | return NULL; |
321 | 0 | } |
322 | | |
323 | 37.6k | ret = talloc(mem_ctx, struct dom_sid); |
324 | 37.6k | if (!ret) { |
325 | 0 | return NULL; |
326 | 0 | } |
327 | 37.6k | sid_copy(ret, dom_sid); |
328 | | |
329 | 37.6k | return ret; |
330 | 37.6k | } |
331 | | |
332 | | /* |
333 | | add a rid to a domain dom_sid to make a full dom_sid. This function |
334 | | returns a new sid in the supplied memory context |
335 | | */ |
336 | | struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx, |
337 | | const struct dom_sid *domain_sid, |
338 | | uint32_t rid) |
339 | 0 | { |
340 | 0 | struct dom_sid *sid; |
341 | |
|
342 | 0 | sid = dom_sid_dup(mem_ctx, domain_sid); |
343 | 0 | if (!sid) return NULL; |
344 | | |
345 | 0 | if (!sid_append_rid(sid, rid)) { |
346 | 0 | talloc_free(sid); |
347 | 0 | return NULL; |
348 | 0 | } |
349 | | |
350 | 0 | return sid; |
351 | 0 | } |
352 | | |
353 | | /* |
354 | | Split up a SID into its domain and RID part |
355 | | */ |
356 | | NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, |
357 | | struct dom_sid **domain, uint32_t *rid) |
358 | 0 | { |
359 | 0 | if (sid->num_auths == 0) { |
360 | 0 | return NT_STATUS_INVALID_PARAMETER; |
361 | 0 | } |
362 | | |
363 | 0 | if (domain) { |
364 | 0 | if (!(*domain = dom_sid_dup(mem_ctx, sid))) { |
365 | 0 | return NT_STATUS_NO_MEMORY; |
366 | 0 | } |
367 | | |
368 | 0 | (*domain)->num_auths -= 1; |
369 | 0 | } |
370 | | |
371 | 0 | if (rid) { |
372 | 0 | *rid = sid->sub_auths[sid->num_auths - 1]; |
373 | 0 | } |
374 | |
|
375 | 0 | return NT_STATUS_OK; |
376 | 0 | } |
377 | | |
378 | | /* |
379 | | return true if the 2nd sid contains or matches the prefix_sid |
380 | | */ |
381 | | bool dom_sid_match_prefix(const struct dom_sid *prefix_sid, |
382 | | const struct dom_sid *sid) |
383 | 41.1k | { |
384 | 41.1k | int i; |
385 | | |
386 | 41.1k | if (!prefix_sid || !sid) { |
387 | 0 | return false; |
388 | 0 | } |
389 | | |
390 | 41.1k | if (prefix_sid->num_auths > sid->num_auths) { |
391 | 0 | return false; |
392 | 0 | } |
393 | | |
394 | 201k | for (i = prefix_sid->num_auths-1; i >= 0; --i) { |
395 | 161k | if (prefix_sid->sub_auths[i] != sid->sub_auths[i]) { |
396 | 993 | return false; |
397 | 993 | } |
398 | 161k | } |
399 | | |
400 | 40.1k | return dom_sid_compare_auth(prefix_sid, sid) == 0; |
401 | 41.1k | } |
402 | | |
403 | | /* |
404 | | return true if the 2nd sid is in the domain given by the first sid |
405 | | */ |
406 | | bool dom_sid_in_domain(const struct dom_sid *domain_sid, |
407 | | const struct dom_sid *sid) |
408 | 111k | { |
409 | 111k | if (!domain_sid || !sid) { |
410 | 37.7k | return false; |
411 | 37.7k | } |
412 | | |
413 | 73.5k | if (sid->num_auths < 2) { |
414 | 20.5k | return false; |
415 | 20.5k | } |
416 | | |
417 | 52.9k | if (domain_sid->num_auths != (sid->num_auths - 1)) { |
418 | 11.8k | return false; |
419 | 11.8k | } |
420 | | |
421 | 41.1k | return dom_sid_match_prefix(domain_sid, sid); |
422 | 52.9k | } |
423 | | |
424 | | bool dom_sid_has_account_domain(const struct dom_sid *sid) |
425 | 0 | { |
426 | 0 | if (sid == NULL) { |
427 | 0 | return false; |
428 | 0 | } |
429 | | |
430 | 0 | if (sid->sid_rev_num != 1) { |
431 | 0 | return false; |
432 | 0 | } |
433 | 0 | if (sid->num_auths != 5) { |
434 | 0 | return false; |
435 | 0 | } |
436 | 0 | if (sid->id_auth[5] != 5) { |
437 | 0 | return false; |
438 | 0 | } |
439 | 0 | if (sid->id_auth[4] != 0) { |
440 | 0 | return false; |
441 | 0 | } |
442 | 0 | if (sid->id_auth[3] != 0) { |
443 | 0 | return false; |
444 | 0 | } |
445 | 0 | if (sid->id_auth[2] != 0) { |
446 | 0 | return false; |
447 | 0 | } |
448 | 0 | if (sid->id_auth[1] != 0) { |
449 | 0 | return false; |
450 | 0 | } |
451 | 0 | if (sid->id_auth[0] != 0) { |
452 | 0 | return false; |
453 | 0 | } |
454 | 0 | if (sid->sub_auths[0] != 21) { |
455 | 0 | return false; |
456 | 0 | } |
457 | | |
458 | 0 | return true; |
459 | 0 | } |
460 | | |
461 | | bool dom_sid_is_valid_account_domain(const struct dom_sid *sid) |
462 | 0 | { |
463 | | /* |
464 | | * We expect S-1-5-21-9-8-7, but we don't |
465 | | * allow S-1-5-21-0-0-0 as this is used |
466 | | * for claims and compound identities. |
467 | | * |
468 | | * With this structure: |
469 | | * |
470 | | * struct dom_sid { |
471 | | * uint8_t sid_rev_num; |
472 | | * int8_t num_auths; [range(0,15)] |
473 | | * uint8_t id_auth[6]; |
474 | | * uint32_t sub_auths[15]; |
475 | | * } |
476 | | * |
477 | | * S-1-5-21-9-8-7 looks like this: |
478 | | * {1, 4, {0,0,0,0,0,5}, {21,9,8,7,0,0,0,0,0,0,0,0,0,0,0}}; |
479 | | */ |
480 | 0 | if (sid == NULL) { |
481 | 0 | return false; |
482 | 0 | } |
483 | | |
484 | 0 | if (sid->sid_rev_num != 1) { |
485 | 0 | return false; |
486 | 0 | } |
487 | 0 | if (sid->num_auths != 4) { |
488 | 0 | return false; |
489 | 0 | } |
490 | 0 | if (sid->id_auth[5] != 5) { |
491 | 0 | return false; |
492 | 0 | } |
493 | 0 | if (sid->id_auth[4] != 0) { |
494 | 0 | return false; |
495 | 0 | } |
496 | 0 | if (sid->id_auth[3] != 0) { |
497 | 0 | return false; |
498 | 0 | } |
499 | 0 | if (sid->id_auth[2] != 0) { |
500 | 0 | return false; |
501 | 0 | } |
502 | 0 | if (sid->id_auth[1] != 0) { |
503 | 0 | return false; |
504 | 0 | } |
505 | 0 | if (sid->id_auth[0] != 0) { |
506 | 0 | return false; |
507 | 0 | } |
508 | 0 | if (sid->sub_auths[0] != 21) { |
509 | 0 | return false; |
510 | 0 | } |
511 | 0 | if (sid->sub_auths[1] == 0) { |
512 | 0 | return false; |
513 | 0 | } |
514 | 0 | if (sid->sub_auths[2] == 0) { |
515 | 0 | return false; |
516 | 0 | } |
517 | 0 | if (sid->sub_auths[3] == 0) { |
518 | 0 | return false; |
519 | 0 | } |
520 | | |
521 | 0 | return true; |
522 | 0 | } |
523 | | |
524 | | /* |
525 | | Convert a dom_sid to a string, printing into a buffer. Return the |
526 | | string length. If it overflows, return the string length that would |
527 | | result (buflen needs to be +1 for the terminating 0). |
528 | | */ |
529 | | static int dom_sid_string_buf(const struct dom_sid *sid, char *buf, int buflen) |
530 | 580k | { |
531 | 580k | int i, ofs, ret; |
532 | 580k | uint64_t ia; |
533 | | |
534 | 580k | if (!sid) { |
535 | 0 | return strlcpy(buf, "(NULL SID)", buflen); |
536 | 0 | } |
537 | | |
538 | 580k | ia = ((uint64_t)sid->id_auth[5]) + |
539 | 580k | ((uint64_t)sid->id_auth[4] << 8 ) + |
540 | 580k | ((uint64_t)sid->id_auth[3] << 16) + |
541 | 580k | ((uint64_t)sid->id_auth[2] << 24) + |
542 | 580k | ((uint64_t)sid->id_auth[1] << 32) + |
543 | 580k | ((uint64_t)sid->id_auth[0] << 40); |
544 | | |
545 | 580k | ret = snprintf(buf, buflen, "S-%"PRIu8"-", sid->sid_rev_num); |
546 | 580k | if (ret < 0) { |
547 | 0 | return ret; |
548 | 0 | } |
549 | 580k | ofs = ret; |
550 | | |
551 | 580k | if (ia >= UINT32_MAX) { |
552 | 134k | ret = snprintf(buf+ofs, MAX(buflen-ofs, 0), "0x%"PRIx64, ia); |
553 | 445k | } else { |
554 | 445k | ret = snprintf(buf+ofs, MAX(buflen-ofs, 0), "%"PRIu64, ia); |
555 | 445k | } |
556 | 580k | if (ret < 0) { |
557 | 0 | return ret; |
558 | 0 | } |
559 | 580k | ofs += ret; |
560 | | |
561 | 1.34M | for (i = 0; i < sid->num_auths; i++) { |
562 | 762k | ret = snprintf( |
563 | 762k | buf+ofs, |
564 | 762k | MAX(buflen-ofs, 0), |
565 | 762k | "-%"PRIu32, |
566 | 762k | sid->sub_auths[i]); |
567 | 762k | if (ret < 0) { |
568 | 0 | return ret; |
569 | 0 | } |
570 | 762k | ofs += ret; |
571 | 762k | } |
572 | 580k | return ofs; |
573 | 580k | } |
574 | | |
575 | | /* |
576 | | convert a dom_sid to a string |
577 | | */ |
578 | | char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) |
579 | 15.4k | { |
580 | 15.4k | char buf[DOM_SID_STR_BUFLEN]; |
581 | 15.4k | char *result; |
582 | 15.4k | int len; |
583 | | |
584 | 15.4k | len = dom_sid_string_buf(sid, buf, sizeof(buf)); |
585 | | |
586 | 15.4k | if ((len < 0) || (len+1 > sizeof(buf))) { |
587 | 0 | return talloc_strdup(mem_ctx, "(SID ERR)"); |
588 | 0 | } |
589 | | |
590 | | /* |
591 | | * Avoid calling strlen (via talloc_strdup), we already have |
592 | | * the length |
593 | | */ |
594 | 15.4k | result = (char *)talloc_memdup(mem_ctx, buf, len+1); |
595 | 15.4k | if (result == NULL) { |
596 | 0 | return NULL; |
597 | 0 | } |
598 | | |
599 | | /* |
600 | | * beautify the talloc_report output |
601 | | */ |
602 | 15.4k | talloc_set_name_const(result, result); |
603 | 15.4k | return result; |
604 | 15.4k | } |
605 | | |
606 | | char *dom_sid_str_buf(const struct dom_sid *sid, struct dom_sid_buf *dst) |
607 | 565k | { |
608 | 565k | int ret; |
609 | 565k | ret = dom_sid_string_buf(sid, dst->buf, sizeof(dst->buf)); |
610 | 565k | if ((ret < 0) || (ret >= sizeof(dst->buf))) { |
611 | 0 | strlcpy(dst->buf, "(INVALID SID)", sizeof(dst->buf)); |
612 | 0 | } |
613 | 565k | return dst->buf; |
614 | 565k | } |