From 6d7eb1adf32b223a771237bf063517974f632036 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 6 Jan 2004 01:59:20 +0000 Subject: Merge winbind from Samba 3.0 onto HEAD. Changes include: - header changes for better pre-compiled headers (tridge) - get a list of sids for a given user (tridge) - fix function prototype and a few other minor things Andrew Bartlett (This used to be commit 60107efdc61247034424d008c6f1eb4d46a19881) --- source3/nsswitch/wbinfo.c | 44 ++++++++++- source3/nsswitch/winbind_nss_linux.c | 149 +++++++++++++++++++++++++++++++++++ source3/nsswitch/winbindd.c | 3 + source3/nsswitch/winbindd.h | 1 - source3/nsswitch/winbindd_acct.c | 1 + source3/nsswitch/winbindd_ads.c | 3 +- source3/nsswitch/winbindd_cache.c | 1 + source3/nsswitch/winbindd_cm.c | 3 +- source3/nsswitch/winbindd_dual.c | 1 + source3/nsswitch/winbindd_group.c | 86 ++++++++++++++++++++ source3/nsswitch/winbindd_misc.c | 1 + source3/nsswitch/winbindd_nss.h | 3 + source3/nsswitch/winbindd_pam.c | 1 + source3/nsswitch/winbindd_rpc.c | 1 + source3/nsswitch/winbindd_sid.c | 20 +++-- source3/nsswitch/winbindd_user.c | 1 + source3/nsswitch/winbindd_util.c | 3 +- source3/nsswitch/winbindd_wins.c | 1 + 18 files changed, 309 insertions(+), 14 deletions(-) (limited to 'source3') diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 55eeb9fa39..792af84827 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -136,6 +136,37 @@ static BOOL wbinfo_get_usergroups(char *user) return True; } + +/* List group SIDs a user SID is a member of */ +static BOOL wbinfo_get_usersids(char *user_sid) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + int i; + const char *s; + + ZERO_STRUCT(response); + + /* Send request */ + fstrcpy(request.data.sid, user_sid); + + result = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response); + + if (result != NSS_STATUS_SUCCESS) + return False; + + s = response.extra_data; + for (i = 0; i < response.data.num_entries; i++) { + d_printf("%s\n", s); + s += strlen(s) + 1; + } + + SAFE_FREE(response.extra_data); + + return True; +} + /* Convert NetBIOS name to IP */ static BOOL wbinfo_wins_byname(char *name) @@ -920,7 +951,8 @@ enum { OPT_SET_AUTH_USER = 1000, OPT_GET_AUTH_USER, OPT_DOMAIN_NAME, - OPT_SEQUENCE + OPT_SEQUENCE, + OPT_USERSIDS }; int main(int argc, char **argv) @@ -961,11 +993,12 @@ int main(int argc, char **argv) { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show all most info we have about the domain" }, { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, + { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" }, { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, - { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operatio", "domain" }, + { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" }, POPT_COMMON_VERSION POPT_TABLEEND }; @@ -1099,6 +1132,13 @@ int main(int argc, char **argv) goto done; } break; + case OPT_USERSIDS: + if (!wbinfo_get_usersids(string_arg)) { + d_printf("Could not get group SIDs for user SID %s\n", + string_arg); + goto done; + } + break; case 'a': { BOOL got_error = False; diff --git a/source3/nsswitch/winbind_nss_linux.c b/source3/nsswitch/winbind_nss_linux.c index 125bc8ccda..ac4a861ff1 100644 --- a/source3/nsswitch/winbind_nss_linux.c +++ b/source3/nsswitch/winbind_nss_linux.c @@ -860,3 +860,152 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, done: return ret; } + + +/* return a list of group SIDs for a user SID */ +NSS_STATUS +_nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, + char *buffer, size_t buf_size, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + if (buf_size < response.length - sizeof(response)) { + ret = NSS_STATUS_TRYAGAIN; + errno = *errnop = ERANGE; + goto done; + } + + *num_groups = response.data.num_entries; + *group_sids = buffer; + memcpy(buffer, response.extra_data, response.length - sizeof(response)); + errno = *errnop = 0; + + done: + free_response(&response); + return ret; +} + + +/* map a user or group name to a SID string */ +NSS_STATUS +_nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.name.name, name, + sizeof(request.data.name.name) - 1); + request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strcpy(*sid, response.data.sid.sid); + +failed: + free_response(&response); + return ret; +} + +/* map a sid string to a user or group name */ +NSS_STATUS +_nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + static char sep_char; + unsigned needed; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid); +#endif + + /* we need to fetch the separator first time through */ + if (!sep_char) { + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + ret = winbindd_request(WINBINDD_INFO, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + sep_char = response.data.info.winbind_separator; + free_response(&response); + } + + + strncpy(request.data.sid, sid, + sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_LOOKUPSID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + needed = + strlen(response.data.name.dom_name) + + strlen(response.data.name.name) + 2; + + if (buflen < needed) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + snprintf(buffer, needed, "%s%c%s", + response.data.name.dom_name, + sep_char, + response.data.name.name); + + *name = buffer; + *errnop = errno = 0; + +failed: + free_response(&response); + return ret; +} diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index b1c0c67d52..8ce528d2b0 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" BOOL opt_nocache = False; @@ -220,6 +221,7 @@ static struct dispatch_table dispatch_table[] = { { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, + { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" }, /* Group functions */ @@ -722,6 +724,7 @@ static void process_loop(void) && *(uint32 *) &state->request != sizeof(state->request)) { DEBUG(0,("process_loop: Invalid request size from pid %lu: %d bytes sent, should be %ld\n", (unsigned long)state->request.pid, *(uint32 *) &state->request, (unsigned long)sizeof(state->request))); + DEBUGADD(0, ("This usually means that you are running old wbinfo, pam_winbind or libnss_winbind clients\n")); remove_client(state); break; diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 7c612ea61b..5dbe422bc1 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -25,7 +25,6 @@ #ifndef _WINBINDD_H #define _WINBINDD_H -#include "includes.h" #include "nterr.h" #include "winbindd_nss.h" diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c index 0c06df7fdd..08b9e2172c 100644 --- a/source3/nsswitch/winbindd_acct.c +++ b/source3/nsswitch/winbindd_acct.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index f8582aee99..90b83bccd0 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #ifdef HAVE_ADS @@ -553,8 +554,6 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, done: if (res) ads_msgfree(ads, res); - if (msg) - ads_msgfree(ads, msg); return status; } diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 91ef38a368..a3c1706b75 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index c255d21102..2b561be31d 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -56,6 +56,7 @@ */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS @@ -183,8 +184,6 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i machine_password, lp_workgroup()))) { DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result))); - if (NT_STATUS_IS_OK(result)) - result = NT_STATUS_UNSUCCESSFUL; } } new_conn->cli->use_kerberos = False; diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index 167630b0e1..a9796afa36 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -29,6 +29,7 @@ */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 1c5d6acf51..180a3db8e2 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS @@ -1081,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; +} + diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 19beddc304..08b5be827d 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 2383db551e..0dd00e9b39 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -121,6 +121,9 @@ enum winbindd_cmd { /* find the location of our privileged pipe */ WINBINDD_PRIV_PIPE_DIR, + /* return a list of group sids for a user sid */ + WINBINDD_GETUSERSIDS, + WINBINDD_NUM_CMDS }; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index dba2fe8ba4..31698b4798 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 81bbc774d1..f619aa3564 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index 0faeec5636..7c4c8d804a 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS @@ -83,6 +84,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) char *name_domain, *name_user; DOM_SID sid; struct winbindd_domain *domain; + char *p; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0'; @@ -90,13 +92,19 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0'; - DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, - state->request.data.name.dom_name, - lp_winbind_separator(), - state->request.data.name.name)); + /* cope with the name being a fully qualified name */ + p = strstr(state->request.data.name.name, lp_winbind_separator()); + if (p) { + *p = 0; + name_domain = state->request.data.name.name; + name_user = p+1; + } else { + name_domain = state->request.data.name.dom_name; + name_user = state->request.data.name.name; + } - name_domain = state->request.data.name.dom_name; - name_user = state->request.data.name.name; + DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, + name_domain, lp_winbind_separator(), name_user)); if ((domain = find_domain_from_name(name_domain)) == NULL) { DEBUG(0, ("could not find domain entry for domain %s\n", diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index eab88c842e..903a2a8bfa 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 95aaec3b1e..f29ed37650 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS @@ -340,7 +341,7 @@ struct winbindd_domain *find_domain_from_sid(DOM_SID *sid) /* Given a domain sid, return the struct winbindd domain info for it */ -struct winbindd_domain *find_our_domain() +struct winbindd_domain *find_our_domain(void) { struct winbindd_domain *domain; diff --git a/source3/nsswitch/winbindd_wins.c b/source3/nsswitch/winbindd_wins.c index 49bee2dc9f..bc982d0044 100644 --- a/source3/nsswitch/winbindd_wins.c +++ b/source3/nsswitch/winbindd_wins.c @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" #include "winbindd.h" #undef DBGC_CLASS -- cgit