1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

r17459: As by Jerry's word commit this without his review.

This patch add some missing async functions to
solve UID/GID -> SID requests not just out of the cache,
but down the remote idmap if necessary.

This patch solves the problem of servers not showing users/groups names
for allocated UID/GIDs when joined to a group of servers that share a
prepopulated idmap backend.

Also correctly resolve UID/GIDs to SIDs when looking ACLs from the
windows security tab on teh same situation.

Simo.
(This used to be commit b8578bfab6)
This commit is contained in:
Simo Sorce 2006-08-08 15:33:09 +00:00 committed by Gerald (Jerry) Carter
parent 21da07ba1f
commit 3bb5b15801
6 changed files with 246 additions and 50 deletions

View File

@ -1524,3 +1524,113 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
do_async_domain(mem_ctx, domain, &request, query_user_recv,
(void *)cont, private_data);
}
/* The following uid2sid/gid2sid functions has been contributed by
* Keith Reynolds <Keith.Reynolds@centrify.com> */
static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ, const char *sid) = c;
if (!success) {
DEBUG(5, ("Could not trigger uid2sid\n"));
cont(private_data, False, NULL);
return;
}
if (response->result != WINBINDD_OK) {
DEBUG(5, ("uid2sid returned an error\n"));
cont(private_data, False, NULL);
return;
}
cont(private_data, True, response->data.sid.sid);
}
void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
void (*cont)(void *private_data, BOOL success, const char *sid),
void *private_data)
{
struct winbindd_request request;
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_UID2SID;
request.data.uid = uid;
do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, cont, private_data);
}
enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
DOM_SID sid;
NTSTATUS result;
DEBUG(3,("[%5lu]: uid to sid %lu\n",
(unsigned long)state->pid,
(unsigned long) state->request.data.uid));
/* Find sid for this uid and return it, possibly ask the slow remote idmap */
result = idmap_uid_to_sid(&sid, state->request.data.uid, IDMAP_FLAG_NONE);
if (NT_STATUS_IS_OK(result)) {
sid_to_string(state->response.data.sid.sid, &sid);
state->response.data.sid.type = SID_NAME_USER;
return WINBINDD_OK;
}
return WINBINDD_ERROR;
}
static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
struct winbindd_response *response,
void *c, void *private_data)
{
void (*cont)(void *priv, BOOL succ, const char *sid) = c;
if (!success) {
DEBUG(5, ("Could not trigger gid2sid\n"));
cont(private_data, False, NULL);
return;
}
cont(private_data, True, response->data.sid.sid);
}
void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
void (*cont)(void *private_data, BOOL success, const char *sid),
void *private_data)
{
struct winbindd_request request;
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_GID2SID;
request.data.gid = gid;
do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, cont, private_data);
}
enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
DOM_SID sid;
NTSTATUS result;
DEBUG(3,("[%5lu]: gid %lu to sid\n",
(unsigned long)state->pid,
(unsigned long) state->request.data.gid));
/* Find sid for this gid and return it, possibly ask the slow remote idmap */
result = idmap_gid_to_sid(&sid, state->request.data.gid, IDMAP_FLAG_NONE);
if (NT_STATUS_IS_OK(result)) {
sid_to_string(state->response.data.sid.sid, &sid);
DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
(unsigned long)state->pid,
state->response.data.sid.sid));
state->response.data.sid.type = SID_NAME_DOM_GRP;
return WINBINDD_OK;
}
return WINBINDD_ERROR;
}

View File

@ -357,6 +357,8 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
{ WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
{ WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
{ WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" },
{ WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" },
{ WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" },
{ WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" },
{ WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" },

View File

@ -329,54 +329,16 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
request_ok(state);
}
/* Return a group structure from a gid number */
void winbindd_getgrgid(struct winbindd_cli_state *state)
static void getgrgid_got_sid(struct winbindd_cli_state *state, DOM_SID group_sid)
{
struct winbindd_domain *domain;
DOM_SID group_sid;
enum SID_NAME_USE name_type;
fstring dom_name;
fstring group_name;
size_t gr_mem_len;
size_t num_gr_mem;
char *gr_mem;
NTSTATUS status;
DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.gid));
/* Bug out if the gid isn't in the winbind range */
if ((state->request.data.gid < server_state.gid_low) ||
(state->request.data.gid > server_state.gid_high)) {
request_error(state);
return;
}
/* Get sid from gid */
status = idmap_gid_to_sid(&group_sid, state->request.data.gid, 0);
if (NT_STATUS_IS_OK(status)) {
/* This is a remote one */
goto got_sid;
}
/* Ok, this might be "ours", i.e. an alias */
if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
(name_type == SID_NAME_ALIAS)) {
/* Hey, got an alias */
goto got_sid;
}
DEBUG(1, ("could not convert gid %lu to sid\n",
(unsigned long)state->request.data.gid));
request_error(state);
return;
got_sid:
/* Get name from sid */
if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, dom_name,
@ -423,9 +385,73 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
state->response.length += gr_mem_len;
state->response.extra_data.data = gr_mem;
request_ok(state);
}
static void getgrgid_recv(void *private_data, BOOL success, const char *sid)
{
struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state);
enum SID_NAME_USE name_type;
DOM_SID group_sid;
if (success) {
DEBUG(10,("getgrgid_recv: gid %lu has sid %s\n",
(unsigned long)(state->request.data.gid), sid));
string_to_sid(&group_sid, sid);
getgrgid_got_sid(state, group_sid);
return;
}
/* Ok, this might be "ours", i.e. an alias */
if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
(name_type == SID_NAME_ALIAS)) {
/* Hey, got an alias */
DEBUG(10,("getgrgid_recv: we have an alias with gid %lu and sid %s\n",
(unsigned long)(state->request.data.gid), sid));
getgrgid_got_sid(state, group_sid);
return;
}
DEBUG(1, ("could not convert gid %lu to sid\n",
(unsigned long)state->request.data.gid));
request_error(state);
}
/* Return a group structure from a gid number */
void winbindd_getgrgid(struct winbindd_cli_state *state)
{
DOM_SID group_sid;
NTSTATUS status;
DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.gid));
/* Bug out if the gid isn't in the winbind range */
if ((state->request.data.gid < server_state.gid_low) ||
(state->request.data.gid > server_state.gid_high)) {
request_error(state);
return;
}
/* Get sid from gid */
status = idmap_gid_to_sid(&group_sid, state->request.data.gid, IDMAP_FLAG_NONE);
if (NT_STATUS_IS_OK(status)) {
/* This is a remote one */
getgrgid_got_sid(state, group_sid);
return;
}
DEBUG(10,("winbindd_getgrgid: gid %lu not found in cache, try with the async interface\n",
(unsigned long)state->request.data.gid));
winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, getgrgid_recv, state);
}
/*
* set/get/endgrent functions
*/

View File

@ -140,6 +140,8 @@ enum winbindd_cmd {
* between parent and children */
WINBINDD_DUAL_SID2UID,
WINBINDD_DUAL_SID2GID,
WINBINDD_DUAL_UID2SID,
WINBINDD_DUAL_GID2SID,
WINBINDD_DUAL_IDMAPSET,
/* Wrapper around possibly blocking unix nss calls */

View File

@ -297,11 +297,12 @@ static void uid2sid_lookupname_recv(void *private_data, BOOL success,
enum SID_NAME_USE type);
static void uid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
static void uid2sid_recv(void *private_data, BOOL success, const char *sid);
void winbindd_uid_to_sid(struct winbindd_cli_state *state)
{
DOM_SID sid;
NTSTATUS status;
struct uid2sid_state *uid2sid_state;
DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.uid));
@ -322,6 +323,25 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state)
return;
}
winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
}
static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
{
struct winbindd_cli_state *state = private_data;
struct uid2sid_state *uid2sid_state;
if (success) {
DEBUG(10,("uid2sid: uid %lu has sid %s\n",
(unsigned long)(state->request.data.uid), sid));
fstrcpy(state->response.data.sid.sid, sid);
state->response.data.sid.type = SID_NAME_USER;
request_ok(state);
return;
}
/* preexisitng mapping not found go on */
if (is_in_uid_range(state->request.data.uid)) {
/* This is winbind's, so we should better have succeeded
* above. */
@ -337,9 +357,6 @@ void winbindd_uid_to_sid(struct winbindd_cli_state *state)
return;
}
/* The only chance that this is correct is that winbind trusted
* domains only = yes, and the user exists in nss and the domain. */
uid2sid_state = TALLOC_ZERO_P(state->mem_ctx, struct uid2sid_state);
if (uid2sid_state == NULL) {
DEBUG(0, ("talloc failed\n"));
@ -424,6 +441,8 @@ static void gid2sid_lookupname_recv(void *private_data, BOOL success,
enum SID_NAME_USE type);
static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success);
static void gid2sid_recv(void *private_data, BOOL success, const char *sid);
void winbindd_gid_to_sid(struct winbindd_cli_state *state)
{
DOM_SID sid;
@ -449,6 +468,25 @@ void winbindd_gid_to_sid(struct winbindd_cli_state *state)
return;
}
winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
}
static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
{
struct winbindd_cli_state *state = private_data;
struct gid2sid_state *gid2sid_state;
if (success) {
DEBUG(10,("gid2sid: gid %lu has sid %s\n",
(unsigned long)(state->request.data.gid), sid));
fstrcpy(state->response.data.sid.sid, sid);
state->response.data.sid.type = SID_NAME_DOM_GRP;
request_ok(state);
return;
}
/* preexisitng mapping not found go on */
if (is_in_gid_range(state->request.data.gid)) {
/* This is winbind's, so we should better have succeeded
* above. */

View File

@ -380,15 +380,32 @@ static void getpwnam_name2sid_recv(void *private_data, BOOL success,
winbindd_getpwsid(state, sid);
}
/* Return a password structure given a uid number */
static void getpwuid_recv(void *private_data, BOOL success, const char *sid)
{
struct winbindd_cli_state *state = private_data;
DOM_SID user_sid;
if (!success) {
DEBUG(10,("uid2sid_recv: uid [%lu] to sid mapping failed\n.",
(unsigned long)(state->request.data.uid)));
request_error(state);
return;
}
DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n",
(unsigned long)(state->request.data.uid), sid));
string_to_sid(&user_sid, sid);
winbindd_getpwsid(state, &user_sid);
}
/* Return a password structure given a uid number */
void winbindd_getpwuid(struct winbindd_cli_state *state)
{
DOM_SID user_sid;
NTSTATUS status;
/* Bug out if the uid isn't in the winbind range */
if ((state->request.data.uid < server_state.uid_low ) ||
(state->request.data.uid > server_state.uid_high)) {
request_error(state);
@ -401,14 +418,15 @@ void winbindd_getpwuid(struct winbindd_cli_state *state)
status = idmap_uid_to_sid(&user_sid, state->request.data.uid,
IDMAP_FLAG_QUERY_ONLY | IDMAP_FLAG_CACHE_ONLY);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("Could not find SID for uid %lu\n",
(unsigned long)state->request.data.uid));
request_error(state);
if (NT_STATUS_IS_OK(status)) {
winbindd_getpwsid(state, &user_sid);
return;
}
winbindd_getpwsid(state, &user_sid);
DEBUG(10,("Could not find SID for uid %lu in the cache. Querying idmap backend\n",
(unsigned long)state->request.data.uid));
winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, getpwuid_recv, state);
}
/*