source: branches/samba-3.2.x/source/nsswitch/libwbclient/wbc_sid.c

Last change on this file was 228, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.6

File size: 14.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind client API
5
6 Copyright (C) Gerald (Jerry) Carter 2007
7
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 3 of the License, or (at your option) any later version.
13
14 This library 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 GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23/* Required Headers */
24
25#include "libwbclient.h"
26
27
28/** @brief Convert a binary SID to a character string
29 *
30 * @param sid Binary Security Identifier
31 * @param **sid_string Resulting character string
32 *
33 * @return #wbcErr
34 **/
35
36wbcErr wbcSidToString(const struct wbcDomainSid *sid,
37 char **sid_string)
38{
39 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
40 uint32_t id_auth;
41 int i;
42 char *tmp = NULL;
43
44 if (!sid) {
45 wbc_status = WBC_ERR_INVALID_SID;
46 BAIL_ON_WBC_ERROR(wbc_status);
47 }
48
49 id_auth = sid->id_auth[5] +
50 (sid->id_auth[4] << 8) +
51 (sid->id_auth[3] << 16) +
52 (sid->id_auth[2] << 24);
53
54 tmp = talloc_asprintf(NULL, "S-%d-%d", sid->sid_rev_num, id_auth);
55 BAIL_ON_PTR_ERROR(tmp, wbc_status);
56
57 for (i=0; i<sid->num_auths; i++) {
58 char *tmp2;
59 tmp2 = talloc_asprintf_append(tmp, "-%u", sid->sub_auths[i]);
60 BAIL_ON_PTR_ERROR(tmp2, wbc_status);
61
62 tmp = tmp2;
63 }
64
65 *sid_string = tmp;
66 tmp = NULL;
67
68 wbc_status = WBC_ERR_SUCCESS;
69
70done:
71 talloc_free(tmp);
72
73 return wbc_status;
74}
75
76/** @brief Convert a character string to a binary SID
77 *
78 * @param *str Character string in the form of S-...
79 * @param sid Resulting binary SID
80 *
81 * @return #wbcErr
82 **/
83
84wbcErr wbcStringToSid(const char *str,
85 struct wbcDomainSid *sid)
86{
87 const char *p;
88 char *q;
89 uint32_t x;
90 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
91
92 if (!sid) {
93 wbc_status = WBC_ERR_INVALID_PARAM;
94 BAIL_ON_WBC_ERROR(wbc_status);
95 }
96
97 /* Sanity check for either "S-" or "s-" */
98
99 if (!str
100 || (str[0]!='S' && str[0]!='s')
101 || (str[1]!='-')
102 || (strlen(str)<2))
103 {
104 wbc_status = WBC_ERR_INVALID_PARAM;
105 BAIL_ON_WBC_ERROR(wbc_status);
106 }
107
108 /* Get the SID revision number */
109
110 p = str+2;
111 x = (uint32_t)strtol(p, &q, 10);
112 if (x==0 || !q || *q!='-') {
113 wbc_status = WBC_ERR_INVALID_SID;
114 BAIL_ON_WBC_ERROR(wbc_status);
115 }
116 sid->sid_rev_num = (uint8_t)x;
117
118 /* Next the Identifier Authority. This is stored in big-endian
119 in a 6 byte array. */
120
121 p = q+1;
122 x = (uint32_t)strtol(p, &q, 10);
123 if (!q || *q!='-') {
124 wbc_status = WBC_ERR_INVALID_SID;
125 BAIL_ON_WBC_ERROR(wbc_status);
126 }
127 sid->id_auth[5] = (x & 0x000000ff);
128 sid->id_auth[4] = (x & 0x0000ff00) >> 8;
129 sid->id_auth[3] = (x & 0x00ff0000) >> 16;
130 sid->id_auth[2] = (x & 0xff000000) >> 24;
131 sid->id_auth[1] = 0;
132 sid->id_auth[0] = 0;
133
134 /* now read the the subauthorities */
135
136 p = q +1;
137 sid->num_auths = 0;
138 while (sid->num_auths < WBC_MAXSUBAUTHS) {
139 x=(uint32_t)strtoul(p, &q, 10);
140 if (p == q)
141 break;
142 sid->sub_auths[sid->num_auths++] = x;
143
144 if (q && ((*q!='-') || (*q=='\0')))
145 break;
146 p = q + 1;
147 }
148
149 /* IF we ended early, then the SID could not be converted */
150
151 if (q && *q!='\0') {
152 wbc_status = WBC_ERR_INVALID_SID;
153 BAIL_ON_WBC_ERROR(wbc_status);
154 }
155
156 wbc_status = WBC_ERR_SUCCESS;
157
158done:
159 return wbc_status;
160
161}
162
163/** @brief Convert a domain and name to SID
164 *
165 * @param domain Domain name (possibly "")
166 * @param name User or group name
167 * @param *sid Pointer to the resolved domain SID
168 * @param *name_type Pointet to the SID type
169 *
170 * @return #wbcErr
171 *
172 **/
173
174wbcErr wbcLookupName(const char *domain,
175 const char *name,
176 struct wbcDomainSid *sid,
177 enum wbcSidType *name_type)
178{
179 struct winbindd_request request;
180 struct winbindd_response response;
181 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
182
183 if (!sid || !name_type) {
184 wbc_status = WBC_ERR_INVALID_PARAM;
185 BAIL_ON_WBC_ERROR(wbc_status);
186 }
187
188 /* Initialize request */
189
190 ZERO_STRUCT(request);
191 ZERO_STRUCT(response);
192
193 /* dst is already null terminated from the memset above */
194
195 strncpy(request.data.name.dom_name, domain,
196 sizeof(request.data.name.dom_name)-1);
197 strncpy(request.data.name.name, name,
198 sizeof(request.data.name.name)-1);
199
200 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME,
201 &request,
202 &response);
203 BAIL_ON_WBC_ERROR(wbc_status);
204
205 wbc_status = wbcStringToSid(response.data.sid.sid, sid);
206 BAIL_ON_WBC_ERROR(wbc_status);
207
208 *name_type = (enum wbcSidType)response.data.sid.type;
209
210 wbc_status = WBC_ERR_SUCCESS;
211
212 done:
213 return wbc_status;
214}
215
216/** @brief Convert a SID to a domain and name
217 *
218 * @param *sid Pointer to the domain SID to be resolved
219 * @param domain Resolved Domain name (possibly "")
220 * @param name Resolved User or group name
221 * @param *name_type Pointet to the resolved SID type
222 *
223 * @return #wbcErr
224 *
225 **/
226
227wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
228 char **pdomain,
229 char **pname,
230 enum wbcSidType *pname_type)
231{
232 struct winbindd_request request;
233 struct winbindd_response response;
234 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
235 char *sid_string = NULL;
236 char *domain = NULL;
237 char *name = NULL;
238 enum wbcSidType name_type;
239
240 if (!sid) {
241 wbc_status = WBC_ERR_INVALID_PARAM;
242 BAIL_ON_WBC_ERROR(wbc_status);
243 }
244
245 /* Initialize request */
246
247 ZERO_STRUCT(request);
248 ZERO_STRUCT(response);
249
250 /* dst is already null terminated from the memset above */
251
252 wbc_status = wbcSidToString(sid, &sid_string);
253 BAIL_ON_WBC_ERROR(wbc_status);
254
255 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
256 wbcFreeMemory(sid_string);
257
258 /* Make request */
259
260 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID,
261 &request,
262 &response);
263 BAIL_ON_WBC_ERROR(wbc_status);
264
265 /* Copy out result */
266
267 domain = talloc_strdup(NULL, response.data.name.dom_name);
268 BAIL_ON_PTR_ERROR(domain, wbc_status);
269
270 name = talloc_strdup(NULL, response.data.name.name);
271 BAIL_ON_PTR_ERROR(name, wbc_status);
272
273 name_type = (enum wbcSidType)response.data.name.type;
274
275 wbc_status = WBC_ERR_SUCCESS;
276
277 done:
278 if (WBC_ERROR_IS_OK(wbc_status)) {
279 if (pdomain != NULL) {
280 *pdomain = domain;
281 }
282 if (pname != NULL) {
283 *pname = name;
284 }
285 if (pname_type != NULL) {
286 *pname_type = name_type;
287 }
288 }
289 else {
290 if (name != NULL) {
291 talloc_free(name);
292 }
293 if (domain != NULL) {
294 talloc_free(domain);
295 }
296 }
297
298 return wbc_status;
299}
300
301/** @brief Translate a collection of RIDs within a domain to names
302 *
303 **/
304
305wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
306 int num_rids,
307 uint32_t *rids,
308 const char **pp_domain_name,
309 const char ***pnames,
310 enum wbcSidType **ptypes)
311{
312 size_t i, len, ridbuf_size;
313 char *ridlist;
314 char *p;
315 struct winbindd_request request;
316 struct winbindd_response response;
317 char *sid_string = NULL;
318 char *domain_name = NULL;
319 const char **names = NULL;
320 enum wbcSidType *types = NULL;
321 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
322
323 /* Initialise request */
324
325 ZERO_STRUCT(request);
326 ZERO_STRUCT(response);
327
328 if (!dom_sid || (num_rids == 0)) {
329 wbc_status = WBC_ERR_INVALID_PARAM;
330 BAIL_ON_WBC_ERROR(wbc_status);
331 }
332
333 wbc_status = wbcSidToString(dom_sid, &sid_string);
334 BAIL_ON_WBC_ERROR(wbc_status);
335
336 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
337 wbcFreeMemory(sid_string);
338
339 /* Even if all the Rids were of maximum 32bit values,
340 we would only have 11 bytes per rid in the final array
341 ("4294967296" + \n). Add one more byte for the
342 terminating '\0' */
343
344 ridbuf_size = (sizeof(char)*11) * num_rids + 1;
345
346 ridlist = talloc_zero_array(NULL, char, ridbuf_size);
347 BAIL_ON_PTR_ERROR(ridlist, wbc_status);
348
349 len = 0;
350 for (i=0; i<num_rids && (len-1)>0; i++) {
351 char ridstr[12];
352
353 len = strlen(ridlist);
354 p = ridlist + len;
355
356 snprintf( ridstr, sizeof(ridstr)-1, "%u\n", rids[i]);
357 strncat(p, ridstr, ridbuf_size-len-1);
358 }
359
360 request.extra_data.data = ridlist;
361 request.extra_len = strlen(ridlist)+1;
362
363 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
364 &request,
365 &response);
366 talloc_free(ridlist);
367 BAIL_ON_WBC_ERROR(wbc_status);
368
369 domain_name = talloc_strdup(NULL, response.data.domain_name);
370 BAIL_ON_PTR_ERROR(domain_name, wbc_status);
371
372 names = talloc_array(NULL, const char*, num_rids);
373 BAIL_ON_PTR_ERROR(names, wbc_status);
374
375 types = talloc_array(NULL, enum wbcSidType, num_rids);
376 BAIL_ON_PTR_ERROR(types, wbc_status);
377
378 p = (char *)response.extra_data.data;
379
380 for (i=0; i<num_rids; i++) {
381 char *q;
382
383 if (*p == '\0') {
384 wbc_status = WBC_ERR_INVALID_RESPONSE;
385 BAIL_ON_WBC_ERROR(wbc_status);
386 }
387
388 types[i] = (enum wbcSidType)strtoul(p, &q, 10);
389
390 if (*q != ' ') {
391 wbc_status = WBC_ERR_INVALID_RESPONSE;
392 BAIL_ON_WBC_ERROR(wbc_status);
393 }
394
395 p = q+1;
396
397 if ((q = strchr(p, '\n')) == NULL) {
398 wbc_status = WBC_ERR_INVALID_RESPONSE;
399 BAIL_ON_WBC_ERROR(wbc_status);
400 }
401
402 *q = '\0';
403
404 names[i] = talloc_strdup(names, p);
405 BAIL_ON_PTR_ERROR(names[i], wbc_status);
406
407 p = q+1;
408 }
409
410 if (*p != '\0') {
411 wbc_status = WBC_ERR_INVALID_RESPONSE;
412 BAIL_ON_WBC_ERROR(wbc_status);
413 }
414
415 wbc_status = WBC_ERR_SUCCESS;
416
417 done:
418 if (response.extra_data.data) {
419 free(response.extra_data.data);
420 }
421
422 if (WBC_ERROR_IS_OK(wbc_status)) {
423 *pp_domain_name = domain_name;
424 *pnames = names;
425 *ptypes = types;
426 }
427 else {
428 if (domain_name)
429 talloc_free(domain_name);
430 if (names)
431 talloc_free(names);
432 if (types)
433 talloc_free(types);
434 }
435
436 return wbc_status;
437}
438
439/** @brief Get the groups a user belongs to
440 *
441 **/
442
443wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
444 bool domain_groups_only,
445 uint32_t *num_sids,
446 struct wbcDomainSid **_sids)
447{
448 uint32_t i;
449 const char *s;
450 struct winbindd_request request;
451 struct winbindd_response response;
452 char *sid_string = NULL;
453 struct wbcDomainSid *sids = NULL;
454 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
455 int cmd;
456
457 /* Initialise request */
458
459 ZERO_STRUCT(request);
460 ZERO_STRUCT(response);
461
462 if (!user_sid) {
463 wbc_status = WBC_ERR_INVALID_PARAM;
464 BAIL_ON_WBC_ERROR(wbc_status);
465 }
466
467 wbc_status = wbcSidToString(user_sid, &sid_string);
468 BAIL_ON_WBC_ERROR(wbc_status);
469
470 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
471 wbcFreeMemory(sid_string);
472
473 if (domain_groups_only) {
474 cmd = WINBINDD_GETUSERDOMGROUPS;
475 } else {
476 cmd = WINBINDD_GETUSERSIDS;
477 }
478
479 wbc_status = wbcRequestResponse(cmd,
480 &request,
481 &response);
482 BAIL_ON_WBC_ERROR(wbc_status);
483
484 if (response.data.num_entries &&
485 !response.extra_data.data) {
486 wbc_status = WBC_ERR_INVALID_RESPONSE;
487 BAIL_ON_WBC_ERROR(wbc_status);
488 }
489
490 sids = talloc_array(NULL, struct wbcDomainSid,
491 response.data.num_entries);
492 BAIL_ON_PTR_ERROR(sids, wbc_status);
493
494 s = (const char *)response.extra_data.data;
495 for (i = 0; i < response.data.num_entries; i++) {
496 char *n = strchr(s, '\n');
497 if (n) {
498 *n = '\0';
499 }
500 wbc_status = wbcStringToSid(s, &sids[i]);
501 BAIL_ON_WBC_ERROR(wbc_status);
502 s += strlen(s) + 1;
503 }
504
505 *num_sids = response.data.num_entries;
506 *_sids = sids;
507 sids = NULL;
508 wbc_status = WBC_ERR_SUCCESS;
509
510 done:
511 if (response.extra_data.data) {
512 free(response.extra_data.data);
513 }
514 if (sids) {
515 talloc_free(sids);
516 }
517
518 return wbc_status;
519}
520
521/** @brief Lists Users
522 *
523 **/
524
525wbcErr wbcListUsers(const char *domain_name,
526 uint32_t *_num_users,
527 const char ***_users)
528{
529 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
530 struct winbindd_request request;
531 struct winbindd_response response;
532 uint32_t num_users = 0;
533 const char **users = NULL;
534 const char *next;
535
536 /* Initialise request */
537
538 ZERO_STRUCT(request);
539 ZERO_STRUCT(response);
540
541 if (domain_name) {
542 strncpy(request.domain_name, domain_name,
543 sizeof(request.domain_name)-1);
544 }
545
546 wbc_status = wbcRequestResponse(WINBINDD_LIST_USERS,
547 &request,
548 &response);
549 BAIL_ON_WBC_ERROR(wbc_status);
550
551 /* Look through extra data */
552
553 next = (const char *)response.extra_data.data;
554 while (next) {
555 const char **tmp;
556 const char *current = next;
557 char *k = strchr(next, ',');
558 if (k) {
559 k[0] = '\0';
560 next = k+1;
561 } else {
562 next = NULL;
563 }
564
565 tmp = talloc_realloc(NULL, users,
566 const char *,
567 num_users+1);
568 BAIL_ON_PTR_ERROR(tmp, wbc_status);
569 users = tmp;
570
571 users[num_users] = talloc_strdup(users, current);
572 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
573
574 num_users++;
575 }
576
577 *_num_users = num_users;
578 *_users = users;
579 users = NULL;
580 wbc_status = WBC_ERR_SUCCESS;
581
582 done:
583 if (response.extra_data.data) {
584 free(response.extra_data.data);
585 }
586 if (users) {
587 talloc_free(users);
588 }
589 return wbc_status;
590}
591
592/** @brief Lists Groups
593 *
594 **/
595
596wbcErr wbcListGroups(const char *domain_name,
597 uint32_t *_num_groups,
598 const char ***_groups)
599{
600 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
601 struct winbindd_request request;
602 struct winbindd_response response;
603 uint32_t num_groups = 0;
604 const char **groups = NULL;
605 const char *next;
606
607 /* Initialise request */
608
609 ZERO_STRUCT(request);
610 ZERO_STRUCT(response);
611
612 if (domain_name) {
613 strncpy(request.domain_name, domain_name,
614 sizeof(request.domain_name)-1);
615 }
616
617 wbc_status = wbcRequestResponse(WINBINDD_LIST_GROUPS,
618 &request,
619 &response);
620 BAIL_ON_WBC_ERROR(wbc_status);
621
622 /* Look through extra data */
623
624 next = (const char *)response.extra_data.data;
625 while (next) {
626 const char **tmp;
627 const char *current = next;
628 char *k = strchr(next, ',');
629 if (k) {
630 k[0] = '\0';
631 next = k+1;
632 } else {
633 next = NULL;
634 }
635
636 tmp = talloc_realloc(NULL, groups,
637 const char *,
638 num_groups+1);
639 BAIL_ON_PTR_ERROR(tmp, wbc_status);
640 groups = tmp;
641
642 groups[num_groups] = talloc_strdup(groups, current);
643 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
644
645 num_groups++;
646 }
647
648 *_num_groups = num_groups;
649 *_groups = groups;
650 groups = NULL;
651 wbc_status = WBC_ERR_SUCCESS;
652
653 done:
654 if (response.extra_data.data) {
655 free(response.extra_data.data);
656 }
657 if (groups) {
658 talloc_free(groups);
659 }
660 return wbc_status;
661}
Note: See TracBrowser for help on using the repository browser.