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

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

Update 3.3 to 3.3.9

File size: 15.9 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 {
103 wbc_status = WBC_ERR_INVALID_PARAM;
104 BAIL_ON_WBC_ERROR(wbc_status);
105 }
106
107 /* Get the SID revision number */
108
109 p = str+2;
110 x = (uint32_t)strtol(p, &q, 10);
111 if (x==0 || !q || *q!='-') {
112 wbc_status = WBC_ERR_INVALID_SID;
113 BAIL_ON_WBC_ERROR(wbc_status);
114 }
115 sid->sid_rev_num = (uint8_t)x;
116
117 /* Next the Identifier Authority. This is stored in big-endian
118 in a 6 byte array. */
119
120 p = q+1;
121 x = (uint32_t)strtol(p, &q, 10);
122 if (!q || *q!='-') {
123 wbc_status = WBC_ERR_INVALID_SID;
124 BAIL_ON_WBC_ERROR(wbc_status);
125 }
126 sid->id_auth[5] = (x & 0x000000ff);
127 sid->id_auth[4] = (x & 0x0000ff00) >> 8;
128 sid->id_auth[3] = (x & 0x00ff0000) >> 16;
129 sid->id_auth[2] = (x & 0xff000000) >> 24;
130 sid->id_auth[1] = 0;
131 sid->id_auth[0] = 0;
132
133 /* now read the the subauthorities */
134
135 p = q +1;
136 sid->num_auths = 0;
137 while (sid->num_auths < WBC_MAXSUBAUTHS) {
138 x=(uint32_t)strtoul(p, &q, 10);
139 if (p == q)
140 break;
141 if (q == NULL) {
142 wbc_status = WBC_ERR_INVALID_SID;
143 BAIL_ON_WBC_ERROR(wbc_status);
144 }
145 sid->sub_auths[sid->num_auths++] = x;
146
147 if ((*q!='-') || (*q=='\0'))
148 break;
149 p = q + 1;
150 }
151
152 /* IF we ended early, then the SID could not be converted */
153
154 if (q && *q!='\0') {
155 wbc_status = WBC_ERR_INVALID_SID;
156 BAIL_ON_WBC_ERROR(wbc_status);
157 }
158
159 wbc_status = WBC_ERR_SUCCESS;
160
161done:
162 return wbc_status;
163
164}
165
166/** @brief Convert a domain and name to SID
167 *
168 * @param domain Domain name (possibly "")
169 * @param name User or group name
170 * @param *sid Pointer to the resolved domain SID
171 * @param *name_type Pointet to the SID type
172 *
173 * @return #wbcErr
174 *
175 **/
176
177wbcErr wbcLookupName(const char *domain,
178 const char *name,
179 struct wbcDomainSid *sid,
180 enum wbcSidType *name_type)
181{
182 struct winbindd_request request;
183 struct winbindd_response response;
184 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
185
186 if (!sid || !name_type) {
187 wbc_status = WBC_ERR_INVALID_PARAM;
188 BAIL_ON_WBC_ERROR(wbc_status);
189 }
190
191 /* Initialize request */
192
193 ZERO_STRUCT(request);
194 ZERO_STRUCT(response);
195
196 /* dst is already null terminated from the memset above */
197
198 strncpy(request.data.name.dom_name, domain,
199 sizeof(request.data.name.dom_name)-1);
200 strncpy(request.data.name.name, name,
201 sizeof(request.data.name.name)-1);
202
203 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME,
204 &request,
205 &response);
206 BAIL_ON_WBC_ERROR(wbc_status);
207
208 wbc_status = wbcStringToSid(response.data.sid.sid, sid);
209 BAIL_ON_WBC_ERROR(wbc_status);
210
211 *name_type = (enum wbcSidType)response.data.sid.type;
212
213 wbc_status = WBC_ERR_SUCCESS;
214
215 done:
216 return wbc_status;
217}
218
219/** @brief Convert a SID to a domain and name
220 *
221 * @param *sid Pointer to the domain SID to be resolved
222 * @param pdomain Resolved Domain name (possibly "")
223 * @param pname Resolved User or group name
224 * @param *pname_type Pointet to the resolved SID type
225 *
226 * @return #wbcErr
227 *
228 **/
229
230wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
231 char **pdomain,
232 char **pname,
233 enum wbcSidType *pname_type)
234{
235 struct winbindd_request request;
236 struct winbindd_response response;
237 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
238 char *sid_string = NULL;
239 char *domain = NULL;
240 char *name = NULL;
241 enum wbcSidType name_type = WBC_SID_NAME_USE_NONE;
242
243 if (!sid) {
244 wbc_status = WBC_ERR_INVALID_PARAM;
245 BAIL_ON_WBC_ERROR(wbc_status);
246 }
247
248 /* Initialize request */
249
250 ZERO_STRUCT(request);
251 ZERO_STRUCT(response);
252
253 /* dst is already null terminated from the memset above */
254
255 wbc_status = wbcSidToString(sid, &sid_string);
256 BAIL_ON_WBC_ERROR(wbc_status);
257
258 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
259 wbcFreeMemory(sid_string);
260
261 /* Make request */
262
263 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID,
264 &request,
265 &response);
266 BAIL_ON_WBC_ERROR(wbc_status);
267
268 /* Copy out result */
269
270 domain = talloc_strdup(NULL, response.data.name.dom_name);
271 BAIL_ON_PTR_ERROR(domain, wbc_status);
272
273 name = talloc_strdup(NULL, response.data.name.name);
274 BAIL_ON_PTR_ERROR(name, wbc_status);
275
276 name_type = (enum wbcSidType)response.data.name.type;
277
278 wbc_status = WBC_ERR_SUCCESS;
279
280 done:
281 if (WBC_ERROR_IS_OK(wbc_status)) {
282 if (pdomain != NULL) {
283 *pdomain = domain;
284 } else {
285 talloc_free(domain);
286 }
287 if (pname != NULL) {
288 *pname = name;
289 } else {
290 talloc_free(name);
291 }
292 if (pname_type != NULL) {
293 *pname_type = name_type;
294 }
295 }
296 else {
297#if 0
298 /*
299 * Found by Coverity: In this particular routine we can't end
300 * up here with a non-NULL name. Further up there are just two
301 * exit paths that lead here, neither of which leave an
302 * allocated name. If you add more paths up there, re-activate
303 * this.
304 */
305 if (name != NULL) {
306 talloc_free(name);
307 }
308#endif
309 if (domain != NULL) {
310 talloc_free(domain);
311 }
312 }
313
314 return wbc_status;
315}
316
317/** @brief Translate a collection of RIDs within a domain to names
318 *
319 **/
320
321wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
322 int num_rids,
323 uint32_t *rids,
324 const char **pp_domain_name,
325 const char ***pnames,
326 enum wbcSidType **ptypes)
327{
328 size_t i, len, ridbuf_size;
329 char *ridlist;
330 char *p;
331 struct winbindd_request request;
332 struct winbindd_response response;
333 char *sid_string = NULL;
334 char *domain_name = NULL;
335 const char **names = NULL;
336 enum wbcSidType *types = NULL;
337 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
338
339 /* Initialise request */
340
341 ZERO_STRUCT(request);
342 ZERO_STRUCT(response);
343
344 if (!dom_sid || (num_rids == 0)) {
345 wbc_status = WBC_ERR_INVALID_PARAM;
346 BAIL_ON_WBC_ERROR(wbc_status);
347 }
348
349 wbc_status = wbcSidToString(dom_sid, &sid_string);
350 BAIL_ON_WBC_ERROR(wbc_status);
351
352 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
353 wbcFreeMemory(sid_string);
354
355 /* Even if all the Rids were of maximum 32bit values,
356 we would only have 11 bytes per rid in the final array
357 ("4294967296" + \n). Add one more byte for the
358 terminating '\0' */
359
360 ridbuf_size = (sizeof(char)*11) * num_rids + 1;
361
362 ridlist = talloc_zero_array(NULL, char, ridbuf_size);
363 BAIL_ON_PTR_ERROR(ridlist, wbc_status);
364
365 len = 0;
366 for (i=0; i<num_rids && (len-1)>0; i++) {
367 char ridstr[12];
368
369 len = strlen(ridlist);
370 p = ridlist + len;
371
372 snprintf( ridstr, sizeof(ridstr)-1, "%u\n", rids[i]);
373 strncat(p, ridstr, ridbuf_size-len-1);
374 }
375
376 request.extra_data.data = ridlist;
377 request.extra_len = strlen(ridlist)+1;
378
379 wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
380 &request,
381 &response);
382 talloc_free(ridlist);
383 BAIL_ON_WBC_ERROR(wbc_status);
384
385 domain_name = talloc_strdup(NULL, response.data.domain_name);
386 BAIL_ON_PTR_ERROR(domain_name, wbc_status);
387
388 names = talloc_array(NULL, const char*, num_rids);
389 BAIL_ON_PTR_ERROR(names, wbc_status);
390
391 types = talloc_array(NULL, enum wbcSidType, num_rids);
392 BAIL_ON_PTR_ERROR(types, wbc_status);
393
394 p = (char *)response.extra_data.data;
395
396 for (i=0; i<num_rids; i++) {
397 char *q;
398
399 if (*p == '\0') {
400 wbc_status = WBC_ERR_INVALID_RESPONSE;
401 BAIL_ON_WBC_ERROR(wbc_status);
402 }
403
404 types[i] = (enum wbcSidType)strtoul(p, &q, 10);
405
406 if (*q != ' ') {
407 wbc_status = WBC_ERR_INVALID_RESPONSE;
408 BAIL_ON_WBC_ERROR(wbc_status);
409 }
410
411 p = q+1;
412
413 if ((q = strchr(p, '\n')) == NULL) {
414 wbc_status = WBC_ERR_INVALID_RESPONSE;
415 BAIL_ON_WBC_ERROR(wbc_status);
416 }
417
418 *q = '\0';
419
420 names[i] = talloc_strdup(names, p);
421 BAIL_ON_PTR_ERROR(names[i], wbc_status);
422
423 p = q+1;
424 }
425
426 if (*p != '\0') {
427 wbc_status = WBC_ERR_INVALID_RESPONSE;
428 BAIL_ON_WBC_ERROR(wbc_status);
429 }
430
431 wbc_status = WBC_ERR_SUCCESS;
432
433 done:
434 if (response.extra_data.data) {
435 free(response.extra_data.data);
436 }
437
438 if (WBC_ERROR_IS_OK(wbc_status)) {
439 *pp_domain_name = domain_name;
440 *pnames = names;
441 *ptypes = types;
442 }
443 else {
444 if (domain_name)
445 talloc_free(domain_name);
446 if (names)
447 talloc_free(names);
448 if (types)
449 talloc_free(types);
450 }
451
452 return wbc_status;
453}
454
455/** @brief Get the groups a user belongs to
456 *
457 **/
458
459wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
460 bool domain_groups_only,
461 uint32_t *num_sids,
462 struct wbcDomainSid **_sids)
463{
464 uint32_t i;
465 const char *s;
466 struct winbindd_request request;
467 struct winbindd_response response;
468 char *sid_string = NULL;
469 struct wbcDomainSid *sids = NULL;
470 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
471 int cmd;
472
473 /* Initialise request */
474
475 ZERO_STRUCT(request);
476 ZERO_STRUCT(response);
477
478 if (!user_sid) {
479 wbc_status = WBC_ERR_INVALID_PARAM;
480 BAIL_ON_WBC_ERROR(wbc_status);
481 }
482
483 wbc_status = wbcSidToString(user_sid, &sid_string);
484 BAIL_ON_WBC_ERROR(wbc_status);
485
486 strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
487 wbcFreeMemory(sid_string);
488
489 if (domain_groups_only) {
490 cmd = WINBINDD_GETUSERDOMGROUPS;
491 } else {
492 cmd = WINBINDD_GETUSERSIDS;
493 }
494
495 wbc_status = wbcRequestResponse(cmd,
496 &request,
497 &response);
498 BAIL_ON_WBC_ERROR(wbc_status);
499
500 if (response.data.num_entries &&
501 !response.extra_data.data) {
502 wbc_status = WBC_ERR_INVALID_RESPONSE;
503 BAIL_ON_WBC_ERROR(wbc_status);
504 }
505
506 sids = talloc_array(NULL, struct wbcDomainSid,
507 response.data.num_entries);
508 BAIL_ON_PTR_ERROR(sids, wbc_status);
509
510 s = (const char *)response.extra_data.data;
511 for (i = 0; i < response.data.num_entries; i++) {
512 char *n = strchr(s, '\n');
513 if (n) {
514 *n = '\0';
515 }
516 wbc_status = wbcStringToSid(s, &sids[i]);
517 BAIL_ON_WBC_ERROR(wbc_status);
518 s += strlen(s) + 1;
519 }
520
521 *num_sids = response.data.num_entries;
522 *_sids = sids;
523 sids = NULL;
524 wbc_status = WBC_ERR_SUCCESS;
525
526 done:
527 if (response.extra_data.data) {
528 free(response.extra_data.data);
529 }
530 if (sids) {
531 talloc_free(sids);
532 }
533
534 return wbc_status;
535}
536
537/** @brief Lists Users
538 *
539 **/
540
541wbcErr wbcListUsers(const char *domain_name,
542 uint32_t *_num_users,
543 const char ***_users)
544{
545 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
546 struct winbindd_request request;
547 struct winbindd_response response;
548 uint32_t num_users = 0;
549 const char **users = NULL;
550 const char *next;
551
552 /* Initialise request */
553
554 ZERO_STRUCT(request);
555 ZERO_STRUCT(response);
556
557 if (domain_name) {
558 strncpy(request.domain_name, domain_name,
559 sizeof(request.domain_name)-1);
560 }
561
562 wbc_status = wbcRequestResponse(WINBINDD_LIST_USERS,
563 &request,
564 &response);
565 BAIL_ON_WBC_ERROR(wbc_status);
566
567 /* Look through extra data */
568
569 next = (const char *)response.extra_data.data;
570 while (next) {
571 const char **tmp;
572 const char *current = next;
573 char *k = strchr(next, ',');
574 if (k) {
575 k[0] = '\0';
576 next = k+1;
577 } else {
578 next = NULL;
579 }
580
581 tmp = talloc_realloc(NULL, users,
582 const char *,
583 num_users+1);
584 BAIL_ON_PTR_ERROR(tmp, wbc_status);
585 users = tmp;
586
587 users[num_users] = talloc_strdup(users, current);
588 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
589
590 num_users++;
591 }
592
593 *_num_users = num_users;
594 *_users = users;
595 users = NULL;
596 wbc_status = WBC_ERR_SUCCESS;
597
598 done:
599 if (response.extra_data.data) {
600 free(response.extra_data.data);
601 }
602 if (users) {
603 talloc_free(users);
604 }
605 return wbc_status;
606}
607
608/** @brief Lists Groups
609 *
610 **/
611
612wbcErr wbcListGroups(const char *domain_name,
613 uint32_t *_num_groups,
614 const char ***_groups)
615{
616 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
617 struct winbindd_request request;
618 struct winbindd_response response;
619 uint32_t num_groups = 0;
620 const char **groups = NULL;
621 const char *next;
622
623 /* Initialise request */
624
625 ZERO_STRUCT(request);
626 ZERO_STRUCT(response);
627
628 if (domain_name) {
629 strncpy(request.domain_name, domain_name,
630 sizeof(request.domain_name)-1);
631 }
632
633 wbc_status = wbcRequestResponse(WINBINDD_LIST_GROUPS,
634 &request,
635 &response);
636 BAIL_ON_WBC_ERROR(wbc_status);
637
638 /* Look through extra data */
639
640 next = (const char *)response.extra_data.data;
641 while (next) {
642 const char **tmp;
643 const char *current = next;
644 char *k = strchr(next, ',');
645 if (k) {
646 k[0] = '\0';
647 next = k+1;
648 } else {
649 next = NULL;
650 }
651
652 tmp = talloc_realloc(NULL, groups,
653 const char *,
654 num_groups+1);
655 BAIL_ON_PTR_ERROR(tmp, wbc_status);
656 groups = tmp;
657
658 groups[num_groups] = talloc_strdup(groups, current);
659 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
660
661 num_groups++;
662 }
663
664 *_num_groups = num_groups;
665 *_groups = groups;
666 groups = NULL;
667 wbc_status = WBC_ERR_SUCCESS;
668
669 done:
670 if (response.extra_data.data) {
671 free(response.extra_data.data);
672 }
673 if (groups) {
674 talloc_free(groups);
675 }
676 return wbc_status;
677}
678
679wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
680 char **pdomain,
681 char **pfullname,
682 enum wbcSidType *pname_type)
683{
684 wbcErr wbc_status;
685 char *domain = NULL;
686 char *name = NULL;
687 enum wbcSidType name_type;
688
689 wbc_status = wbcLookupSid(sid, &domain, &name, &name_type);
690 BAIL_ON_WBC_ERROR(wbc_status);
691
692 if (name_type == WBC_SID_NAME_USER) {
693 uid_t uid;
694 struct passwd *pwd;
695
696 wbc_status = wbcSidToUid(sid, &uid);
697 BAIL_ON_WBC_ERROR(wbc_status);
698
699 wbc_status = wbcGetpwuid(uid, &pwd);
700 BAIL_ON_WBC_ERROR(wbc_status);
701
702 wbcFreeMemory(name);
703
704 name = talloc_strdup(NULL, pwd->pw_gecos);
705 BAIL_ON_PTR_ERROR(name, wbc_status);
706 }
707
708 wbc_status = WBC_ERR_SUCCESS;
709
710 done:
711 if (WBC_ERROR_IS_OK(wbc_status)) {
712 *pdomain = domain;
713 *pfullname = name;
714 *pname_type = name_type;
715 } else {
716 wbcFreeMemory(domain);
717 wbcFreeMemory(name);
718 }
719
720 return wbc_status;
721}
Note: See TracBrowser for help on using the repository browser.