Merge winbind from Samba 3.0 onto HEAD.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 6 Jan 2004 01:59:20 +0000 (01:59 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 6 Jan 2004 01:59:20 +0000 (01:59 +0000)
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

18 files changed:
source/nsswitch/wbinfo.c
source/nsswitch/winbind_nss_linux.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd.h
source/nsswitch/winbindd_acct.c
source/nsswitch/winbindd_ads.c
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_cm.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_misc.c
source/nsswitch/winbindd_nss.h
source/nsswitch/winbindd_pam.c
source/nsswitch/winbindd_rpc.c
source/nsswitch/winbindd_sid.c
source/nsswitch/winbindd_user.c
source/nsswitch/winbindd_util.c
source/nsswitch/winbindd_wins.c

index 55eeb9fa394a45c7cbf5d7247045bc1f02514898..792af84827f4e182296fafdb4e6ae150e14afb95 100644 (file)
@@ -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;
 
index 125bc8ccdaf9b6e9f3aff8f854e21bdad1d3c465..ac4a861ff1b8f643ea3c4e9c54f0f5923026f987 100644 (file)
@@ -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;
+}
index b1c0c67d52b1235f45ea1bbf04e7fb284517f117..8ce528d2b0d7ab8101c366b7530e304e2191d41d 100644 (file)
@@ -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;
index 7c612ea61b4dff4dae8439a9c20c7e370fed2ca4..5dbe422bc148ca4563b7f07a245095216480c5b0 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef _WINBINDD_H
 #define _WINBINDD_H
 
-#include "includes.h"
 #include "nterr.h"
 
 #include "winbindd_nss.h"
index 0c06df7fdd4670a434ec835c939a2bbdea08554f..08b9e2172c7fdda541c47d95dc66b846d530c870 100644 (file)
@@ -20,6 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index f8582aee99dd6af8de63686a09add42022d406b2..90b83bccd0b8ab295b9c5315abfaee004b47ccc6 100644 (file)
@@ -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;
 }
index 91ef38a3685c141c19584d341e68211ee9788c2c..a3c1706b75dbdd2a2a7b01f5580cd8419a8b7d9a 100644 (file)
@@ -22,6 +22,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index c255d21102f48671c8d03f05f453b833257b5f44..2b561be31db48bb3caf8daba1ab426e87754e80c 100644 (file)
@@ -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;
index 167630b0e1ff09ac0e8ed8126027a0093412017c..a9796afa3679712e0e6c18617e5b0bac81e0618d 100644 (file)
@@ -29,6 +29,7 @@
 
  */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index 1c5d6acf514af925cf571f2baab4103b7cbbd26d..180a3db8e2e02c0968972a10cbcf516284a0e9dc 100644 (file)
@@ -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;
+}
+
index 19beddc304b62147940fb87cce6a36ccabf79db4..08b5be827d1faea93a486faf3ec98799573c07de 100644 (file)
@@ -21,6 +21,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index 2383db551e5eb3ac79be46c316faa34502f283fe..0dd00e9b39edb955b4bc96ab1e3c621bd1ab5800 100644 (file)
@@ -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
 };
 
index dba2fe8ba48dda0ed5244cfc975ba845a15a8a55..31698b479820632980e6ce2d1eb429c09162e004 100644 (file)
@@ -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
index 81bbc774d142cf4bdf1496951c80a2fcddbca6cd..f619aa3564aa0d7faa4a632afcbc6f05253788b1 100644 (file)
@@ -21,6 +21,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index 0faeec56369bd025e1ba8e980623c06d900335ee..7c4c8d804a813a7ff00dcc289ed7654e6a75c3fa 100644 (file)
@@ -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", 
index eab88c842eac75aa3a436c956a91ff12303b7b54..903a2a8bfaf269ed995e21b9c15b5c2fdc174fef 100644 (file)
@@ -22,6 +22,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
index 95aaec3b1ee79463f9e521980e829ef88a252044..f29ed376502a275c99bff8f76a91f88b06acedc3 100644 (file)
@@ -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;
 
index 49bee2dc9f741e69a5677df14ba90e99de1edada..bc982d00443fb749f5061f595118a235b119da44 100644 (file)
@@ -21,6 +21,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS