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:
parent
21da07ba1f
commit
3bb5b15801
@ -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;
|
||||
}
|
||||
|
@ -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" },
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user