2 Unix SMB/CIFS implementation.
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 2000
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.
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.
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/>.
24 #include "nsswitch/winbind_nss.h"
27 #define DBGC_CLASS DBGC_WINBIND
29 NSS_STATUS winbindd_request_response(int req_type,
30 struct winbindd_request *request,
31 struct winbindd_response *response);
33 /* Call winbindd to convert a name to a sid */
35 bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
36 enum lsa_SidType *name_type)
38 struct winbindd_request request;
39 struct winbindd_response response;
42 if (!sid || !name_type)
45 /* Send off request */
48 ZERO_STRUCT(response);
50 fstrcpy(request.data.name.dom_name, dom_name);
51 fstrcpy(request.data.name.name, name);
53 if ((result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request,
54 &response)) == NSS_STATUS_SUCCESS) {
55 if (!string_to_sid(sid, response.data.sid.sid))
57 *name_type = (enum lsa_SidType)response.data.sid.type;
60 return result == NSS_STATUS_SUCCESS;
63 /* Call winbindd to convert sid to name */
65 bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
66 const char **domain, const char **name,
67 enum lsa_SidType *name_type)
69 struct winbindd_request request;
70 struct winbindd_response response;
73 /* Initialise request */
76 ZERO_STRUCT(response);
78 fstrcpy(request.data.sid, sid_string_static(sid));
82 result = winbindd_request_response(WINBINDD_LOOKUPSID, &request,
85 if (result != NSS_STATUS_SUCCESS) {
92 *domain = talloc_strdup(mem_ctx, response.data.name.dom_name);
93 if (*domain == NULL) {
94 DEBUG(0, ("talloc failed\n"));
99 *name = talloc_strdup(mem_ctx, response.data.name.name);
101 DEBUG(0, ("talloc failed\n"));
106 *name_type = (enum lsa_SidType)response.data.name.type;
108 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
109 sid_string_static(sid), response.data.name.dom_name,
110 response.data.name.name));
114 bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
115 const DOM_SID *domain_sid,
116 int num_rids, uint32 *rids,
117 const char **domain_name,
118 const char ***names, enum lsa_SidType **types)
124 struct winbindd_request request;
125 struct winbindd_response response;
132 /* Initialise request */
134 ZERO_STRUCT(request);
135 ZERO_STRUCT(response);
137 fstrcpy(request.data.sid, sid_string_static(domain_sid));
143 for (i=0; i<num_rids; i++) {
144 sprintf_append(mem_ctx, &ridlist, &len, &buflen,
148 if (ridlist == NULL) {
152 request.extra_data.data = ridlist;
153 request.extra_len = strlen(ridlist)+1;
155 result = winbindd_request_response(WINBINDD_LOOKUPRIDS,
156 &request, &response);
158 TALLOC_FREE(ridlist);
160 if (result != NSS_STATUS_SUCCESS) {
164 *domain_name = talloc_strdup(mem_ctx, response.data.domain_name);
166 *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
167 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
169 if ((*names == NULL) || (*types == NULL)) {
173 p = (char *)response.extra_data.data;
175 for (i=0; i<num_rids; i++) {
179 DEBUG(10, ("Got invalid reply: %s\n",
180 (char *)response.extra_data.data));
184 (*types)[i] = (enum lsa_SidType)strtoul(p, &q, 10);
187 DEBUG(10, ("Got invalid reply: %s\n",
188 (char *)response.extra_data.data));
196 DEBUG(10, ("Got invalid reply: %s\n",
197 (char *)response.extra_data.data));
203 (*names)[i] = talloc_strdup(*names, p);
209 DEBUG(10, ("Got invalid reply: %s\n",
210 (char *)response.extra_data.data));
214 SAFE_FREE(response.extra_data.data);
224 /* Call winbindd to convert SID to uid */
226 bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
228 struct winbindd_request request;
229 struct winbindd_response response;
236 /* Initialise request */
238 ZERO_STRUCT(request);
239 ZERO_STRUCT(response);
241 sid_to_string(sid_str, sid);
242 fstrcpy(request.data.sid, sid_str);
246 result = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response);
248 /* Copy out result */
250 if (result == NSS_STATUS_SUCCESS) {
251 *puid = response.data.uid;
254 return (result == NSS_STATUS_SUCCESS);
257 /* Call winbindd to convert uid to sid */
259 bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
261 struct winbindd_request request;
262 struct winbindd_response response;
268 /* Initialise request */
270 ZERO_STRUCT(request);
271 ZERO_STRUCT(response);
273 request.data.uid = uid;
277 result = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response);
279 /* Copy out result */
281 if (result == NSS_STATUS_SUCCESS) {
282 if (!string_to_sid(sid, response.data.sid.sid))
285 sid_copy(sid, &global_sid_NULL);
288 return (result == NSS_STATUS_SUCCESS);
291 /* Call winbindd to convert SID to gid */
293 bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
295 struct winbindd_request request;
296 struct winbindd_response response;
303 /* Initialise request */
305 ZERO_STRUCT(request);
306 ZERO_STRUCT(response);
308 sid_to_string(sid_str, sid);
309 fstrcpy(request.data.sid, sid_str);
313 result = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response);
315 /* Copy out result */
317 if (result == NSS_STATUS_SUCCESS) {
318 *pgid = response.data.gid;
321 return (result == NSS_STATUS_SUCCESS);
324 /* Call winbindd to convert gid to sid */
326 bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
328 struct winbindd_request request;
329 struct winbindd_response response;
335 /* Initialise request */
337 ZERO_STRUCT(request);
338 ZERO_STRUCT(response);
340 request.data.gid = gid;
344 result = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response);
346 /* Copy out result */
348 if (result == NSS_STATUS_SUCCESS) {
349 if (!string_to_sid(sid, response.data.sid.sid))
352 sid_copy(sid, &global_sid_NULL);
355 return (result == NSS_STATUS_SUCCESS);
358 /* Call winbindd to convert SID to uid */
360 bool winbind_sids_to_unixids(struct id_map *ids, int num_ids)
362 struct winbindd_request request;
363 struct winbindd_response response;
368 /* Initialise request */
370 ZERO_STRUCT(request);
371 ZERO_STRUCT(response);
373 request.extra_len = num_ids * sizeof(DOM_SID);
375 sids = (DOM_SID *)SMB_MALLOC(request.extra_len);
376 for (i = 0; i < num_ids; i++) {
377 sid_copy(&sids[i], ids[i].sid);
380 request.extra_data.data = (char *)sids;
384 result = winbindd_request_response(WINBINDD_SIDS_TO_XIDS, &request, &response);
386 /* Copy out result */
388 if (result == NSS_STATUS_SUCCESS) {
389 struct unixid *wid = (struct unixid *)response.extra_data.data;
391 for (i = 0; i < num_ids; i++) {
392 if (wid[i].type == -1) {
393 ids[i].status = ID_UNMAPPED;
395 ids[i].status = ID_MAPPED;
396 ids[i].xid.type = wid[i].type;
397 ids[i].xid.id = wid[i].id;
402 SAFE_FREE(request.extra_data.data);
403 SAFE_FREE(response.extra_data.data);
405 return (result == NSS_STATUS_SUCCESS);
408 bool winbind_allocate_uid(uid_t *uid)
410 struct winbindd_request request;
411 struct winbindd_response response;
414 /* Initialise request */
416 ZERO_STRUCT(request);
417 ZERO_STRUCT(response);
421 result = winbindd_request_response(WINBINDD_ALLOCATE_UID,
422 &request, &response);
424 if (result != NSS_STATUS_SUCCESS)
427 /* Copy out result */
428 *uid = response.data.uid;
433 bool winbind_allocate_gid(gid_t *gid)
435 struct winbindd_request request;
436 struct winbindd_response response;
439 /* Initialise request */
441 ZERO_STRUCT(request);
442 ZERO_STRUCT(response);
446 result = winbindd_request_response(WINBINDD_ALLOCATE_GID,
447 &request, &response);
449 if (result != NSS_STATUS_SUCCESS)
452 /* Copy out result */
453 *gid = response.data.gid;
458 bool winbind_set_mapping(const struct id_map *map)
460 struct winbindd_request request;
461 struct winbindd_response response;
464 /* Initialise request */
466 ZERO_STRUCT(request);
467 ZERO_STRUCT(response);
471 request.data.dual_idmapset.id = map->xid.id;
472 request.data.dual_idmapset.type = map->xid.type;
473 sid_to_string(request.data.dual_idmapset.sid, map->sid);
475 result = winbindd_request_response(WINBINDD_SET_MAPPING, &request, &response);
477 return (result == NSS_STATUS_SUCCESS);
480 bool winbind_set_uid_hwm(unsigned long id)
482 struct winbindd_request request;
483 struct winbindd_response response;
486 /* Initialise request */
488 ZERO_STRUCT(request);
489 ZERO_STRUCT(response);
493 request.data.dual_idmapset.id = id;
494 request.data.dual_idmapset.type = ID_TYPE_UID;
496 result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
498 return (result == NSS_STATUS_SUCCESS);
501 bool winbind_set_gid_hwm(unsigned long id)
503 struct winbindd_request request;
504 struct winbindd_response response;
507 /* Initialise request */
509 ZERO_STRUCT(request);
510 ZERO_STRUCT(response);
514 request.data.dual_idmapset.id = id;
515 request.data.dual_idmapset.type = ID_TYPE_GID;
517 result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
519 return (result == NSS_STATUS_SUCCESS);
522 /**********************************************************************
523 simple wrapper function to see if winbindd is alive
524 **********************************************************************/
526 bool winbind_ping( void )
530 result = winbindd_request_response(WINBINDD_PING, NULL, NULL);
532 return result == NSS_STATUS_SUCCESS;
535 /**********************************************************************
538 result == NSS_STATUS_UNAVAIL: winbind not around
539 result == NSS_STATUS_NOTFOUND: winbind around, but domain missing
541 Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off and
542 when winbind return WINBINDD_ERROR. So the semantics of this routine depends
543 on winbind_on. Grepping for winbind_off I just found 3 places where winbind
544 is turned off, and this does not conflict (as far as I have seen) with the
545 callers of is_trusted_domains.
547 I *hate* global variables....
551 **********************************************************************/
553 NSS_STATUS wb_is_trusted_domain(const char *domain)
555 struct winbindd_request request;
556 struct winbindd_response response;
560 ZERO_STRUCT(request);
561 ZERO_STRUCT(response);
563 fstrcpy(request.domain_name, domain);
565 return winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response);