summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd_group.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch/winbindd_group.c')
-rw-r--r--source3/nsswitch/winbindd_group.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index d951b3433e..15bdc11036 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -1082,3 +1082,88 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
return result;
}
+
+
+/* Get user supplementary sids. This is equivalent to the
+ winbindd_getgroups() function but it involves a SID->SIDs mapping
+ rather than a NAME->SID->SIDS->GIDS mapping, which means we avoid
+ idmap. This call is designed to be used with applications that need
+ to do ACL evaluation themselves. Note that the cached info3 data is
+ not used
+
+ this function assumes that the SID that comes in is a user SID. If
+ you pass in another type of SID then you may get unpredictable
+ results.
+*/
+enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state)
+{
+ DOM_SID user_sid;
+ NTSTATUS status;
+ DOM_SID **user_grpsids;
+ struct winbindd_domain *domain;
+ enum winbindd_result result = WINBINDD_ERROR;
+ unsigned int i;
+ TALLOC_CTX *mem_ctx;
+ char *ret;
+ uint32 num_groups;
+ unsigned ofs, ret_size = 0;
+
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
+ if (!string_to_sid(&user_sid, state->request.data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n", state->request.data.sid));
+ return WINBINDD_ERROR;
+ }
+
+ if (!(mem_ctx = talloc_init("winbindd_getusersids(%s)",
+ state->request.data.username))) {
+ return WINBINDD_ERROR;
+ }
+
+ /* Get info for the domain */
+ if ((domain = find_domain_from_sid(&user_sid)) == NULL) {
+ DEBUG(0,("could not find domain entry for sid %s\n",
+ sid_string_static(&user_sid)));
+ goto done;
+ }
+
+ status = domain->methods->lookup_usergroups(domain, mem_ctx,
+ &user_sid, &num_groups,
+ &user_grpsids);
+ if (!NT_STATUS_IS_OK(status))
+ goto done;
+
+ if (num_groups == 0) {
+ goto no_groups;
+ }
+
+ /* work out the response size */
+ for (i = 0; i < num_groups; i++) {
+ const char *s = sid_string_static(user_grpsids[i]);
+ ret_size += strlen(s) + 1;
+ }
+
+ /* build the reply */
+ ret = malloc(ret_size);
+ if (!ret) goto done;
+ ofs = 0;
+ for (i = 0; i < num_groups; i++) {
+ const char *s = sid_string_static(user_grpsids[i]);
+ safe_strcpy(ret + ofs, s, ret_size - ofs);
+ ofs += strlen(ret+ofs) + 1;
+ }
+
+no_groups:
+ /* Send data back to client */
+ state->response.data.num_entries = num_groups;
+ state->response.extra_data = ret;
+ state->response.length += ret_size;
+ result = WINBINDD_OK;
+
+ done:
+ talloc_destroy(mem_ctx);
+
+ return result;
+}
+