summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2006-08-08 15:33:09 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:35 -0500
commit3bb5b158017d5bad82bfb4a9e29187549e665446 (patch)
tree3d1e2b2808d1f3a6ae0aafad63d3ee37a9060087
parent21da07ba1fdbef9d8fadfb9bf9fa23afc0a665d1 (diff)
downloadsamba-3bb5b158017d5bad82bfb4a9e29187549e665446.tar.gz
samba-3bb5b158017d5bad82bfb4a9e29187549e665446.tar.bz2
samba-3bb5b158017d5bad82bfb4a9e29187549e665446.zip
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 b8578bfab6a04fcd65a2e65f507067459e326077)
-rw-r--r--source3/nsswitch/winbindd_async.c110
-rw-r--r--source3/nsswitch/winbindd_dual.c2
-rw-r--r--source3/nsswitch/winbindd_group.c104
-rw-r--r--source3/nsswitch/winbindd_nss.h2
-rw-r--r--source3/nsswitch/winbindd_sid.c46
-rw-r--r--source3/nsswitch/winbindd_user.c32
6 files changed, 246 insertions, 50 deletions
diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c
index 808e73209d..4edf46dbee 100644
--- a/source3/nsswitch/winbindd_async.c
+++ b/source3/nsswitch/winbindd_async.c
@@ -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;
+}
diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c
index b4d4a794ae..874b480214 100644
--- a/source3/nsswitch/winbindd_dual.c
+++ b/source3/nsswitch/winbindd_dual.c
@@ -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" },
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 5528b6c78e..5cab6eb663 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -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
*/
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index b36c0147a7..4a95a3cf42 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -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 */
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index 4a9e17e4c7..7af6373167 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -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. */
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 8a0ebbafa5..f08efa044f 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -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);
}
/*