2 Unix SMB/CIFS implementation.
4 Winbind daemon - sid related functions
6 Copyright (C) Tim Potter 2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DBGC_CLASS DBGC_WINBIND
29 /* Convert a string */
31 static void lookupsid_recv(void *private, BOOL success
,
32 const char *dom_name
, const char *name
,
33 enum SID_NAME_USE type
);
35 enum winbindd_result
winbindd_lookupsid(struct winbindd_cli_state
*state
)
39 /* Ensure null termination */
40 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
42 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state
->pid
,
43 state
->request
.data
.sid
));
45 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
46 DEBUG(5, ("%s not a SID\n", state
->request
.data
.sid
));
47 return WINBINDD_ERROR
;
50 winbindd_lookupsid_async(state
->mem_ctx
, &sid
, lookupsid_recv
, state
);
51 return WINBINDD_PENDING
;
54 static void lookupsid_recv(void *private, BOOL success
,
55 const char *dom_name
, const char *name
,
56 enum SID_NAME_USE type
)
58 struct winbindd_cli_state
*state
=
59 talloc_get_type_abort(private, struct winbindd_cli_state
);
62 DEBUG(5, ("lookupsid returned an error\n"));
63 state
->response
.result
= WINBINDD_ERROR
;
64 request_finished(state
);
68 fstrcpy(state
->response
.data
.name
.dom_name
, dom_name
);
69 fstrcpy(state
->response
.data
.name
.name
, name
);
70 state
->response
.data
.name
.type
= type
;
71 state
->response
.result
= WINBINDD_OK
;
72 request_finished(state
);
76 * Look up the SID for a qualified name.
79 static void lookupname_recv(void *private, BOOL success
,
80 const DOM_SID
*sid
, enum SID_NAME_USE type
);
82 enum winbindd_result
winbindd_lookupname(struct winbindd_cli_state
*state
)
84 char *name_domain
, *name_user
;
87 /* Ensure null termination */
88 state
->request
.data
.sid
[sizeof(state
->request
.data
.name
.dom_name
)-1]='\0';
90 /* Ensure null termination */
91 state
->request
.data
.sid
[sizeof(state
->request
.data
.name
.name
)-1]='\0';
93 /* cope with the name being a fully qualified name */
94 p
= strstr(state
->request
.data
.name
.name
, lp_winbind_separator());
97 name_domain
= state
->request
.data
.name
.name
;
100 name_domain
= state
->request
.data
.name
.dom_name
;
101 name_user
= state
->request
.data
.name
.name
;
104 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state
->pid
,
105 name_domain
, lp_winbind_separator(), name_user
));
107 winbindd_lookupname_async(state
->mem_ctx
, name_domain
, name_user
,
108 lookupname_recv
, state
);
109 return WINBINDD_PENDING
;
112 static void lookupname_recv(void *private, BOOL success
,
113 const DOM_SID
*sid
, enum SID_NAME_USE type
)
115 struct winbindd_cli_state
*state
=
116 talloc_get_type_abort(private, struct winbindd_cli_state
);
119 DEBUG(5, ("lookupname returned an error\n"));
120 state
->response
.result
= WINBINDD_ERROR
;
121 request_finished(state
);
125 sid_to_string(state
->response
.data
.sid
.sid
, sid
);
126 state
->response
.data
.sid
.type
= type
;
127 state
->response
.result
= WINBINDD_OK
;
128 request_finished(state
);
132 static struct winbindd_child static_idmap_child
;
134 void init_idmap_child(void)
136 setup_domain_child(NULL
, &static_idmap_child
, "idmap");
139 struct winbindd_child
*idmap_child(void)
141 return &static_idmap_child
;
144 /* Convert a sid to a uid. We assume we only have one rid attached to the
147 static void sid2uid_recv(void *private, BOOL success
, uid_t uid
);
149 enum winbindd_result
winbindd_sid_to_uid(struct winbindd_cli_state
*state
)
154 /* Ensure null termination */
155 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
157 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state
->pid
,
158 state
->request
.data
.sid
));
160 if (idmap_proxyonly()) {
161 DEBUG(8, ("IDMAP proxy only\n"));
162 return WINBINDD_ERROR
;
165 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
166 DEBUG(1, ("Could not get convert sid %s from string\n",
167 state
->request
.data
.sid
));
168 return WINBINDD_ERROR
;
171 /* Query only the local tdb, everything else might possibly block */
173 result
= idmap_sid_to_uid(&sid
, &(state
->response
.data
.uid
),
174 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
176 if (NT_STATUS_IS_OK(result
)) {
180 winbindd_sid2uid_async(state
->mem_ctx
, &sid
, sid2uid_recv
, state
);
181 return WINBINDD_PENDING
;
184 static void sid2uid_recv(void *private, BOOL success
, uid_t uid
)
186 struct winbindd_cli_state
*state
=
187 talloc_get_type_abort(private, struct winbindd_cli_state
);
190 DEBUG(5, ("Could not convert sid %s\n",
191 state
->request
.data
.sid
));
192 state
->response
.result
= WINBINDD_ERROR
;
193 request_finished(state
);
197 state
->response
.result
= WINBINDD_OK
;
198 state
->response
.data
.uid
= uid
;
199 request_finished(state
);
202 /* Convert a sid to a gid. We assume we only have one rid attached to the
205 static void sid2gid_recv(void *private, BOOL success
, gid_t gid
);
207 enum winbindd_result
winbindd_sid_to_gid(struct winbindd_cli_state
*state
)
212 /* Ensure null termination */
213 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
215 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state
->pid
,
216 state
->request
.data
.sid
));
218 if (idmap_proxyonly()) {
219 DEBUG(8, ("IDMAP proxy only\n"));
220 return WINBINDD_ERROR
;
223 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
224 DEBUG(1, ("Could not get convert sid %s from string\n",
225 state
->request
.data
.sid
));
226 return WINBINDD_ERROR
;
229 /* Query only the local tdb, everything else might possibly block */
231 result
= idmap_sid_to_gid(&sid
, &(state
->response
.data
.gid
),
232 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
234 if (NT_STATUS_IS_OK(result
)) {
238 winbindd_sid2gid_async(state
->mem_ctx
, &sid
, sid2gid_recv
, state
);
239 return WINBINDD_PENDING
;
242 static void sid2gid_recv(void *private, BOOL success
, gid_t gid
)
244 struct winbindd_cli_state
*state
=
245 talloc_get_type_abort(private, struct winbindd_cli_state
);
248 DEBUG(5, ("Could not convert sid %s\n",
249 state
->request
.data
.sid
));
250 state
->response
.result
= WINBINDD_ERROR
;
251 request_finished(state
);
255 state
->response
.result
= WINBINDD_OK
;
256 state
->response
.data
.gid
= gid
;
257 request_finished(state
);
260 /* Convert a uid to a sid */
262 struct uid2sid_state
{
263 struct winbindd_cli_state
*cli_state
;
267 enum SID_NAME_USE type
;
270 static void uid2sid_uid2name_recv(void *private, BOOL success
,
271 const char *username
);
272 static void uid2sid_lookupname_recv(void *private, BOOL success
,
274 enum SID_NAME_USE type
);
275 static void uid2sid_idmap_set_mapping_recv(void *private, BOOL success
);
277 enum winbindd_result
winbindd_uid_to_sid(struct winbindd_cli_state
*state
)
281 struct uid2sid_state
*uid2sid_state
;
283 DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state
->pid
,
284 (unsigned long)state
->request
.data
.uid
));
286 if (idmap_proxyonly()) {
287 DEBUG(8, ("IDMAP proxy only\n"));
288 return WINBINDD_ERROR
;
291 status
= idmap_uid_to_sid(&sid
, state
->request
.data
.uid
,
292 ID_QUERY_ONLY
| ID_CACHE_ONLY
);
294 if (NT_STATUS_IS_OK(status
)) {
295 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
296 state
->response
.data
.sid
.type
= SID_NAME_USER
;
300 if (is_in_uid_range(state
->request
.data
.uid
)) {
301 /* This is winbind's, so we should better have succeeded
303 return WINBINDD_ERROR
;
306 /* The only chance that this is correct is that winbind trusted
307 * domains only = yes, and the user exists in nss and the domain. */
309 if (!lp_winbind_trusted_domains_only()) {
310 return WINBINDD_ERROR
;
313 /* The only chance that this is correct is that winbind trusted
314 * domains only = yes, and the user exists in nss and the domain. */
316 uid2sid_state
= TALLOC_ZERO_P(state
->mem_ctx
, struct uid2sid_state
);
317 if (uid2sid_state
== NULL
) {
318 DEBUG(0, ("talloc failed\n"));
319 return WINBINDD_ERROR
;
322 uid2sid_state
->cli_state
= state
;
323 uid2sid_state
->uid
= state
->request
.data
.uid
;
325 winbindd_uid2name_async(state
->mem_ctx
, state
->request
.data
.uid
,
326 uid2sid_uid2name_recv
, uid2sid_state
);
327 return WINBINDD_PENDING
;
330 static void uid2sid_uid2name_recv(void *private, BOOL success
,
331 const char *username
)
333 struct uid2sid_state
*state
=
334 talloc_get_type_abort(private, struct uid2sid_state
);
336 DEBUG(10, ("uid2sid: uid %lu has name %s\n",
337 (unsigned long)state
->uid
, username
));
339 fstrcpy(state
->name
, username
);
342 state
->cli_state
->response
.result
= WINBINDD_ERROR
;
343 request_finished(state
->cli_state
);
347 winbindd_lookupname_async(state
->cli_state
->mem_ctx
,
348 find_our_domain()->name
, username
,
349 uid2sid_lookupname_recv
, state
);
352 static void uid2sid_lookupname_recv(void *private, BOOL success
,
353 const DOM_SID
*sid
, enum SID_NAME_USE type
)
355 struct uid2sid_state
*state
=
356 talloc_get_type_abort(private, struct uid2sid_state
);
359 if ((!success
) || (type
!= SID_NAME_USER
)) {
360 state
->cli_state
->response
.result
= WINBINDD_ERROR
;
361 request_finished(state
->cli_state
);
369 idmap_set_mapping_async(state
->cli_state
->mem_ctx
, sid
, id
, ID_USERID
,
370 uid2sid_idmap_set_mapping_recv
, state
);
373 static void uid2sid_idmap_set_mapping_recv(void *private, BOOL success
)
375 struct uid2sid_state
*state
=
376 talloc_get_type_abort(private, struct uid2sid_state
);
378 /* don't fail if we can't store it */
380 sid_to_string(state
->cli_state
->response
.data
.sid
.sid
, &state
->sid
);
381 state
->cli_state
->response
.data
.sid
.type
= state
->type
;
382 state
->cli_state
->response
.result
= WINBINDD_OK
;
383 request_finished(state
->cli_state
);
386 /* Convert a gid to a sid */
388 struct gid2sid_state
{
389 struct winbindd_cli_state
*cli_state
;
393 enum SID_NAME_USE type
;
396 static void gid2sid_gid2name_recv(void *private, BOOL success
,
397 const char *groupname
);
398 static void gid2sid_lookupname_recv(void *private, BOOL success
,
400 enum SID_NAME_USE type
);
401 static void gid2sid_idmap_set_mapping_recv(void *private, BOOL success
);
403 enum winbindd_result
winbindd_gid_to_sid(struct winbindd_cli_state
*state
)
407 struct gid2sid_state
*gid2sid_state
;
409 DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state
->pid
,
410 (unsigned long)state
->request
.data
.gid
));
412 if (idmap_proxyonly()) {
413 DEBUG(8, ("IDMAP proxy only\n"));
414 return WINBINDD_ERROR
;
417 status
= idmap_gid_to_sid(&sid
, state
->request
.data
.gid
,
418 ID_QUERY_ONLY
| ID_CACHE_ONLY
);
420 if (NT_STATUS_IS_OK(status
)) {
421 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
422 state
->response
.data
.sid
.type
= SID_NAME_USER
;
426 if (is_in_gid_range(state
->request
.data
.gid
)) {
427 /* This is winbind's, so we should better have succeeded
429 return WINBINDD_ERROR
;
432 /* The only chance that this is correct is that winbind trusted
433 * domains only = yes, and the user exists in nss and the domain. */
435 if (!lp_winbind_trusted_domains_only()) {
436 return WINBINDD_ERROR
;
439 /* The only chance that this is correct is that winbind trusted
440 * domains only = yes, and the user exists in nss and the domain. */
442 gid2sid_state
= TALLOC_ZERO_P(state
->mem_ctx
, struct gid2sid_state
);
443 if (gid2sid_state
== NULL
) {
444 DEBUG(0, ("talloc failed\n"));
445 return WINBINDD_ERROR
;
448 gid2sid_state
->cli_state
= state
;
449 gid2sid_state
->gid
= state
->request
.data
.gid
;
451 winbindd_gid2name_async(state
->mem_ctx
, state
->request
.data
.gid
,
452 gid2sid_gid2name_recv
, gid2sid_state
);
453 return WINBINDD_PENDING
;
456 static void gid2sid_gid2name_recv(void *private, BOOL success
,
457 const char *username
)
459 struct gid2sid_state
*state
=
460 talloc_get_type_abort(private, struct gid2sid_state
);
462 DEBUG(10, ("gid2sid: gid %lu has name %s\n",
463 (unsigned long)state
->gid
, username
));
465 fstrcpy(state
->name
, username
);
468 state
->cli_state
->response
.result
= WINBINDD_ERROR
;
469 request_finished(state
->cli_state
);
473 winbindd_lookupname_async(state
->cli_state
->mem_ctx
,
474 find_our_domain()->name
, username
,
475 gid2sid_lookupname_recv
, state
);
478 static void gid2sid_lookupname_recv(void *private, BOOL success
,
479 const DOM_SID
*sid
, enum SID_NAME_USE type
)
481 struct gid2sid_state
*state
=
482 talloc_get_type_abort(private, struct gid2sid_state
);
486 ((type
!= SID_NAME_DOM_GRP
) && (type
!=SID_NAME_ALIAS
))) {
487 state
->cli_state
->response
.result
= WINBINDD_ERROR
;
488 request_finished(state
->cli_state
);
496 idmap_set_mapping_async(state
->cli_state
->mem_ctx
, sid
, id
, ID_GROUPID
,
497 gid2sid_idmap_set_mapping_recv
, state
);
500 static void gid2sid_idmap_set_mapping_recv(void *private, BOOL success
)
502 struct gid2sid_state
*state
= private;
504 /* don't fail if we can't store it */
506 sid_to_string(state
->cli_state
->response
.data
.sid
.sid
, &state
->sid
);
507 state
->cli_state
->response
.data
.sid
.type
= state
->type
;
508 state
->cli_state
->response
.result
= WINBINDD_OK
;
509 request_finished(state
->cli_state
);
512 enum winbindd_result
winbindd_allocate_rid(struct winbindd_cli_state
*state
)
514 if ( !state
->privileged
) {
515 DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
517 return WINBINDD_ERROR
;
520 async_request(state
->mem_ctx
, idmap_child(),
521 &state
->request
, &state
->response
,
522 request_finished_cont
, state
);
523 return WINBINDD_PENDING
;
526 enum winbindd_result
winbindd_dual_allocate_rid(struct winbindd_domain
*domain
,
527 struct winbindd_cli_state
*state
)
529 /* We tell idmap to always allocate a user RID. There might be a good
530 * reason to keep RID allocation for users to even and groups to
531 * odd. This needs discussion I think. For now only allocate user
534 if (!NT_STATUS_IS_OK(idmap_allocate_rid(&state
->response
.data
.rid
,
536 return WINBINDD_ERROR
;
541 enum winbindd_result
winbindd_allocate_rid_and_gid(struct winbindd_cli_state
*state
)
543 if ( !state
->privileged
) {
544 DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
546 return WINBINDD_ERROR
;
549 async_request(state
->mem_ctx
, idmap_child(),
550 &state
->request
, &state
->response
,
551 request_finished_cont
, state
);
552 return WINBINDD_PENDING
;
555 enum winbindd_result
winbindd_dual_allocate_rid_and_gid(struct winbindd_domain
*domain
,
556 struct winbindd_cli_state
*state
)
561 /* We tell idmap to always allocate a user RID. This is really
562 * historic and needs to be fixed. I *think* this has to do with the
563 * way winbind determines its free RID space. */
565 result
= idmap_allocate_rid(&state
->response
.data
.rid_and_gid
.rid
,
568 if (!NT_STATUS_IS_OK(result
))
569 return WINBINDD_ERROR
;
571 sid_copy(&sid
, get_global_sam_sid());
572 sid_append_rid(&sid
, state
->response
.data
.rid_and_gid
.rid
);
574 result
= idmap_sid_to_gid(&sid
, &state
->response
.data
.rid_and_gid
.gid
,
577 if (!NT_STATUS_IS_OK(result
))
578 return WINBINDD_ERROR
;