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_data
, BOOL success
,
32 const char *dom_name
, const char *name
,
33 enum SID_NAME_USE type
);
35 void 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
));
51 winbindd_lookupsid_async(state
->mem_ctx
, &sid
, lookupsid_recv
, state
);
54 static void lookupsid_recv(void *private_data
, 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_data
, struct winbindd_cli_state
);
62 DEBUG(5, ("lookupsid returned an error\n"));
67 fstrcpy(state
->response
.data
.name
.dom_name
, dom_name
);
68 fstrcpy(state
->response
.data
.name
.name
, name
);
69 state
->response
.data
.name
.type
= type
;
74 * Look up the SID for a qualified name.
77 static void lookupname_recv(void *private_data
, BOOL success
,
78 const DOM_SID
*sid
, enum SID_NAME_USE type
);
80 void winbindd_lookupname(struct winbindd_cli_state
*state
)
82 char *name_domain
, *name_user
;
85 /* Ensure null termination */
86 state
->request
.data
.name
.dom_name
[sizeof(state
->request
.data
.name
.dom_name
)-1]='\0';
88 /* Ensure null termination */
89 state
->request
.data
.name
.name
[sizeof(state
->request
.data
.name
.name
)-1]='\0';
91 /* cope with the name being a fully qualified name */
92 p
= strstr(state
->request
.data
.name
.name
, lp_winbind_separator());
95 name_domain
= state
->request
.data
.name
.name
;
98 name_domain
= state
->request
.data
.name
.dom_name
;
99 name_user
= state
->request
.data
.name
.name
;
102 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state
->pid
,
103 name_domain
, lp_winbind_separator(), name_user
));
105 winbindd_lookupname_async(state
->mem_ctx
, name_domain
, name_user
,
106 lookupname_recv
, state
);
109 static void lookupname_recv(void *private_data
, BOOL success
,
110 const DOM_SID
*sid
, enum SID_NAME_USE type
)
112 struct winbindd_cli_state
*state
=
113 talloc_get_type_abort(private_data
, struct winbindd_cli_state
);
116 DEBUG(5, ("lookupname returned an error\n"));
117 request_error(state
);
121 sid_to_string(state
->response
.data
.sid
.sid
, sid
);
122 state
->response
.data
.sid
.type
= type
;
127 void winbindd_lookuprids(struct winbindd_cli_state
*state
)
129 struct winbindd_domain
*domain
;
132 /* Ensure null termination */
133 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
135 DEBUG(10, ("lookup_rids: %s\n", state
->request
.data
.sid
));
137 if (!string_to_sid(&domain_sid
, state
->request
.data
.sid
)) {
138 DEBUG(5, ("Could not convert %s to SID\n",
139 state
->request
.data
.sid
));
140 request_error(state
);
144 domain
= find_lookup_domain_from_sid(&domain_sid
);
145 if (domain
== NULL
) {
146 DEBUG(10, ("Could not find domain for name %s\n",
147 state
->request
.domain_name
));
148 request_error(state
);
152 sendto_domain(state
, domain
);
155 static struct winbindd_child static_idmap_child
;
157 void init_idmap_child(void)
159 setup_domain_child(NULL
, &static_idmap_child
, "idmap");
162 struct winbindd_child
*idmap_child(void)
164 return &static_idmap_child
;
167 /* Convert a sid to a uid. We assume we only have one rid attached to the
170 static void sid2uid_recv(void *private_data
, BOOL success
, uid_t uid
);
172 void winbindd_sid_to_uid(struct winbindd_cli_state
*state
)
177 /* Ensure null termination */
178 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
180 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state
->pid
,
181 state
->request
.data
.sid
));
183 if (idmap_proxyonly()) {
184 DEBUG(8, ("IDMAP proxy only\n"));
185 request_error(state
);
189 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
190 DEBUG(1, ("Could not get convert sid %s from string\n",
191 state
->request
.data
.sid
));
192 request_error(state
);
196 /* Query only the local tdb, everything else might possibly block */
198 result
= idmap_sid_to_uid(&sid
, &state
->response
.data
.uid
,
199 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
201 if (NT_STATUS_IS_OK(result
)) {
206 winbindd_sid2uid_async(state
->mem_ctx
, &sid
, sid2uid_recv
, state
);
209 static void sid2uid_recv(void *private_data
, BOOL success
, uid_t uid
)
211 struct winbindd_cli_state
*state
=
212 talloc_get_type_abort(private_data
, struct winbindd_cli_state
);
215 DEBUG(5, ("Could not convert sid %s\n",
216 state
->request
.data
.sid
));
217 request_error(state
);
221 state
->response
.data
.uid
= uid
;
225 /* Convert a sid to a gid. We assume we only have one rid attached to the
228 static void sid2gid_recv(void *private_data
, BOOL success
, gid_t gid
);
230 void winbindd_sid_to_gid(struct winbindd_cli_state
*state
)
235 /* Ensure null termination */
236 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
238 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state
->pid
,
239 state
->request
.data
.sid
));
241 if (idmap_proxyonly()) {
242 DEBUG(8, ("IDMAP proxy only\n"));
243 request_error(state
);
247 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
248 DEBUG(1, ("Could not get convert sid %s from string\n",
249 state
->request
.data
.sid
));
250 request_error(state
);
254 /* Query only the local tdb, everything else might possibly block */
256 result
= idmap_sid_to_gid(&sid
, &state
->response
.data
.gid
,
257 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
259 if (NT_STATUS_IS_OK(result
)) {
264 winbindd_sid2gid_async(state
->mem_ctx
, &sid
, sid2gid_recv
, state
);
267 static void sid2gid_recv(void *private_data
, BOOL success
, gid_t gid
)
269 struct winbindd_cli_state
*state
=
270 talloc_get_type_abort(private_data
, struct winbindd_cli_state
);
273 DEBUG(5, ("Could not convert sid %s\n",
274 state
->request
.data
.sid
));
275 request_error(state
);
279 state
->response
.data
.gid
= gid
;
283 /* Convert a uid to a sid */
285 struct uid2sid_state
{
286 struct winbindd_cli_state
*cli_state
;
290 enum SID_NAME_USE type
;
293 static void uid2sid_uid2name_recv(void *private_data
, BOOL success
,
294 const char *username
);
295 static void uid2sid_lookupname_recv(void *private_data
, BOOL success
,
297 enum SID_NAME_USE type
);
298 static void uid2sid_idmap_set_mapping_recv(void *private_data
, BOOL success
);
300 static void uid2sid_recv(void *private_data
, BOOL success
, const char *sid
);
302 void winbindd_uid_to_sid(struct winbindd_cli_state
*state
)
307 DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state
->pid
,
308 (unsigned long)state
->request
.data
.uid
));
310 if (idmap_proxyonly()) {
311 DEBUG(8, ("IDMAP proxy only\n"));
312 request_error(state
);
316 status
= idmap_uid_to_sid(&sid
, state
->request
.data
.uid
,
317 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
319 if (NT_STATUS_IS_OK(status
)) {
320 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
321 state
->response
.data
.sid
.type
= SID_NAME_USER
;
326 winbindd_uid2sid_async(state
->mem_ctx
, state
->request
.data
.uid
, uid2sid_recv
, state
);
329 static void uid2sid_recv(void *private_data
, BOOL success
, const char *sid
)
331 struct winbindd_cli_state
*state
=
332 (struct winbindd_cli_state
*)private_data
;
333 struct uid2sid_state
*uid2sid_state
;
336 DEBUG(10,("uid2sid: uid %lu has sid %s\n",
337 (unsigned long)(state
->request
.data
.uid
), sid
));
338 fstrcpy(state
->response
.data
.sid
.sid
, sid
);
339 state
->response
.data
.sid
.type
= SID_NAME_USER
;
344 /* preexisitng mapping not found go on */
346 if (is_in_uid_range(state
->request
.data
.uid
)) {
347 /* This is winbind's, so we should better have succeeded
349 request_error(state
);
353 /* The only chance that this is correct is that winbind trusted
354 * domains only = yes, and the user exists in nss and the domain. */
356 if (!lp_winbind_trusted_domains_only()) {
357 request_error(state
);
361 uid2sid_state
= TALLOC_ZERO_P(state
->mem_ctx
, struct uid2sid_state
);
362 if (uid2sid_state
== NULL
) {
363 DEBUG(0, ("talloc failed\n"));
364 request_error(state
);
368 uid2sid_state
->cli_state
= state
;
369 uid2sid_state
->uid
= state
->request
.data
.uid
;
371 winbindd_uid2name_async(state
->mem_ctx
, state
->request
.data
.uid
,
372 uid2sid_uid2name_recv
, uid2sid_state
);
375 static void uid2sid_uid2name_recv(void *private_data
, BOOL success
,
376 const char *username
)
378 struct uid2sid_state
*state
=
379 talloc_get_type_abort(private_data
, struct uid2sid_state
);
381 DEBUG(10, ("uid2sid: uid %lu has name %s\n",
382 (unsigned long)state
->uid
, username
));
384 fstrcpy(state
->name
, username
);
387 request_error(state
->cli_state
);
391 winbindd_lookupname_async(state
->cli_state
->mem_ctx
,
392 find_our_domain()->name
, username
,
393 uid2sid_lookupname_recv
, state
);
396 static void uid2sid_lookupname_recv(void *private_data
, BOOL success
,
397 const DOM_SID
*sid
, enum SID_NAME_USE type
)
399 struct uid2sid_state
*state
=
400 talloc_get_type_abort(private_data
, struct uid2sid_state
);
403 if ((!success
) || (type
!= SID_NAME_USER
)) {
404 request_error(state
->cli_state
);
412 idmap_set_mapping_async(state
->cli_state
->mem_ctx
, sid
, id
, ID_USERID
,
413 uid2sid_idmap_set_mapping_recv
, state
);
416 static void uid2sid_idmap_set_mapping_recv(void *private_data
, BOOL success
)
418 struct uid2sid_state
*state
=
419 talloc_get_type_abort(private_data
, struct uid2sid_state
);
421 /* don't fail if we can't store it */
423 sid_to_string(state
->cli_state
->response
.data
.sid
.sid
, &state
->sid
);
424 state
->cli_state
->response
.data
.sid
.type
= state
->type
;
425 request_ok(state
->cli_state
);
428 /* Convert a gid to a sid */
430 struct gid2sid_state
{
431 struct winbindd_cli_state
*cli_state
;
435 enum SID_NAME_USE type
;
438 static void gid2sid_gid2name_recv(void *private_data
, BOOL success
,
439 const char *groupname
);
440 static void gid2sid_lookupname_recv(void *private_data
, BOOL success
,
442 enum SID_NAME_USE type
);
443 static void gid2sid_idmap_set_mapping_recv(void *private_data
, BOOL success
);
445 static void gid2sid_recv(void *private_data
, BOOL success
, const char *sid
);
447 void winbindd_gid_to_sid(struct winbindd_cli_state
*state
)
452 DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state
->pid
,
453 (unsigned long)state
->request
.data
.gid
));
455 if (idmap_proxyonly()) {
456 DEBUG(8, ("IDMAP proxy only\n"));
457 request_error(state
);
461 status
= idmap_gid_to_sid(&sid
, state
->request
.data
.gid
,
462 ID_QUERY_ONLY
|ID_CACHE_ONLY
);
464 if (NT_STATUS_IS_OK(status
)) {
465 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
466 state
->response
.data
.sid
.type
= SID_NAME_DOM_GRP
;
471 winbindd_gid2sid_async(state
->mem_ctx
, state
->request
.data
.gid
, gid2sid_recv
, state
);
474 static void gid2sid_recv(void *private_data
, BOOL success
, const char *sid
)
476 struct winbindd_cli_state
*state
=
477 (struct winbindd_cli_state
*)private_data
;
478 struct gid2sid_state
*gid2sid_state
;
481 DEBUG(10,("gid2sid: gid %lu has sid %s\n",
482 (unsigned long)(state
->request
.data
.gid
), sid
));
483 fstrcpy(state
->response
.data
.sid
.sid
, sid
);
484 state
->response
.data
.sid
.type
= SID_NAME_DOM_GRP
;
489 /* preexisitng mapping not found go on */
491 if (is_in_gid_range(state
->request
.data
.gid
)) {
492 /* This is winbind's, so we should better have succeeded
494 request_error(state
);
498 /* The only chance that this is correct is that winbind trusted
499 * domains only = yes, and the user exists in nss and the domain. */
501 if (!lp_winbind_trusted_domains_only()) {
502 request_error(state
);
506 /* The only chance that this is correct is that winbind trusted
507 * domains only = yes, and the user exists in nss and the domain. */
509 gid2sid_state
= TALLOC_ZERO_P(state
->mem_ctx
, struct gid2sid_state
);
510 if (gid2sid_state
== NULL
) {
511 DEBUG(0, ("talloc failed\n"));
512 request_error(state
);
516 gid2sid_state
->cli_state
= state
;
517 gid2sid_state
->gid
= state
->request
.data
.gid
;
519 winbindd_gid2name_async(state
->mem_ctx
, state
->request
.data
.gid
,
520 gid2sid_gid2name_recv
, gid2sid_state
);
523 static void gid2sid_gid2name_recv(void *private_data
, BOOL success
,
524 const char *username
)
526 struct gid2sid_state
*state
=
527 talloc_get_type_abort(private_data
, struct gid2sid_state
);
529 DEBUG(10, ("gid2sid: gid %lu has name %s\n",
530 (unsigned long)state
->gid
, username
));
532 fstrcpy(state
->name
, username
);
535 request_error(state
->cli_state
);
539 winbindd_lookupname_async(state
->cli_state
->mem_ctx
,
540 find_our_domain()->name
, username
,
541 gid2sid_lookupname_recv
, state
);
544 static void gid2sid_lookupname_recv(void *private_data
, BOOL success
,
545 const DOM_SID
*sid
, enum SID_NAME_USE type
)
547 struct gid2sid_state
*state
=
548 talloc_get_type_abort(private_data
, struct gid2sid_state
);
552 ((type
!= SID_NAME_DOM_GRP
) && (type
!=SID_NAME_ALIAS
))) {
553 request_error(state
->cli_state
);
561 idmap_set_mapping_async(state
->cli_state
->mem_ctx
, sid
, id
, ID_GROUPID
,
562 gid2sid_idmap_set_mapping_recv
, state
);
565 static void gid2sid_idmap_set_mapping_recv(void *private_data
, BOOL success
)
567 struct gid2sid_state
*state
=
568 (struct gid2sid_state
*)private_data
;
570 /* don't fail if we can't store it */
572 sid_to_string(state
->cli_state
->response
.data
.sid
.sid
, &state
->sid
);
573 state
->cli_state
->response
.data
.sid
.type
= state
->type
;
574 request_ok(state
->cli_state
);
577 void winbindd_allocate_uid(struct winbindd_cli_state
*state
)
579 if ( !state
->privileged
) {
580 DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
582 request_error(state
);
586 sendto_child(state
, idmap_child());
589 enum winbindd_result
winbindd_dual_allocate_uid(struct winbindd_domain
*domain
,
590 struct winbindd_cli_state
*state
)
594 if (!NT_STATUS_IS_OK(idmap_allocate_id(&id
, ID_USERID
))) {
595 return WINBINDD_ERROR
;
597 state
->response
.data
.uid
= id
.uid
;
601 void winbindd_allocate_gid(struct winbindd_cli_state
*state
)
603 if ( !state
->privileged
) {
604 DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
606 request_error(state
);
610 sendto_child(state
, idmap_child());
613 enum winbindd_result
winbindd_dual_allocate_gid(struct winbindd_domain
*domain
,
614 struct winbindd_cli_state
*state
)
618 if (!NT_STATUS_IS_OK(idmap_allocate_id(&id
, ID_GROUPID
))) {
619 return WINBINDD_ERROR
;
621 state
->response
.data
.gid
= id
.gid
;