This is the 'winbind default domain' patch from Alexander Bokovoy
authorAndrew Bartlett <abartlet@samba.org>
Fri, 18 Jan 2002 02:37:55 +0000 (02:37 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 18 Jan 2002 02:37:55 +0000 (02:37 +0000)
<a.bokovoy@sam-solutions.net>.

The idea is the domain\username is rather harsh for unix systems - people don't
expect to have to FTP, SSH and (in particular) e-mail with a username like
that.

This 'corrects' that - but is not without its own problems.

As you can see from the changes to files like username.c and wb_client.c (smbd's
winbind client code) a lot of assumptions are made in a lot of places about
lp_winbind_seperator determining a users's status as a domain or local user.

The main change I will shortly be making is to investigate and kill off
winbind_initgroups() - as far as I know it was a workaround for an old bug in
winbind itself (and a bug in RH 5.2) and should no longer be relevent.

I am also going to move to using the 'winbind uid' and 'winbind gid' paramaters
to determine a user/groups's 'local' status, rather than the presence of the
seperator.

As such, this functionality is recommended for servers providing unix services,
but is currently less than optimal for windows clients.

(TODO: remove all references to lp_winbind_seperator() and
lp_winbind_use_default_domain() from smbd)

Andrew Bartlett
(This used to be commit 07a21fcd2311d2d9b430b99303e3532a8c1159e4)

12 files changed:
docs/docbook/manpages/smb.conf.5.sgml
docs/docbook/manpages/winbindd.8.sgml
source3/lib/username.c
source3/libsmb/cli_netlogon.c
source3/nsswitch/wb_client.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_proto.h
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c
source3/param/loadparm.c

index 9e719e1f2acbe617994fca723ec3895ad366afdd..7aa9ea3b9c57539d2c91a3291ac46a26c53af042 100644 (file)
                <listitem><para><link linkend="WINBINDGID"><parameter>winbind gid</parameter></link></para></listitem>
                <listitem><para><link linkend="WINBINDSEPARATOR"><parameter>winbind separator</parameter></link></para></listitem>
                <listitem><para><link linkend="WINBINDUID"><parameter>winbind uid</parameter></link></para></listitem>
+               <listitem><para><link linkend="WINBINDUSEDEFAULTDOMAIN"><parameter>winbind use default domain</parameter></link></para></listitem>
                <listitem><para><link linkend="WINSHOOK"><parameter>wins hook</parameter></link></para></listitem>
                <listitem><para><link linkend="WINSPROXY"><parameter>wins proxy</parameter></link></para></listitem>
                <listitem><para><link linkend="WINSSERVER"><parameter>wins server</parameter></link></para></listitem>
@@ -8195,7 +8196,23 @@ veto files = /.AppleDouble/.bin/.AppleDesktop/Network Trash Folder/
                </varlistentry>
 
 
-
+               <varlistentry>
+               <term>winbind use default domain</term>
+               
+               <varlistentry>
+               <term><anchor id="WINBINDUSEDEFAULTDOMAIN">winbind use default domain</term>
+               <listitem><para>This parameter specifies whether the <ulink url="winbindd.8.html">
+               winbindd(8)</ulink>
+               daemon should operate on users without domain component in their username.  
+                Users without a domain component are treated as is part of the winbindd server's 
+                own domain.  While this does not benifit Windows users, it makes SSH, FTP and e-mail 
+                function in a way much closer to the way they would in a native unix system.</para>
+               
+               <para>Default: <command>winbind use default domain = &lt;falseg&gt; 
+               </command></para>
+               <para>Example: <command>winbind use default domain = true</command></para>
+               </listitem>
+               </varlistentry>
 
 
                <varlistentry>
index af851657f3394e8ba7def1788429c6b2fb5ea5ce..bd1dafa07e8e2799e442f4620a9ab88cba1e3b2f 100644 (file)
@@ -276,6 +276,20 @@ group:          files winbind
                <para>Default: <command>template shell = /bin/false </command>
                </para></listitem>
                </varlistentry>
+
+               <varlistentry>
+               <term>winbind use default domain</term>
+               <listitem><para>This parameter specifies whether the <command>winbindd</command>
+               daemon should operate on users without domain component in their username.  
+                Users without a domain component are treated as is part of the winbindd server's 
+                own domain.  While this does not benifit Windows users, it makes SSH, FTP and e-mail 
+                function in a way much closer to the way they would in a native unix system.</para>
+               
+               <para>Default: <command>winbind use default domain = &lt;falseg&gt; 
+               </command></para>
+               <para>Example: <command>winbind use default domain = true</command></para>
+               </listitem>
+               </varlistentry>
        </variablelist>
 </refsect1>
 
index 9541ebeb087355f4c8dc5c767b3552190e856609..7c8c9c740da3038b3b0bca0c1cb128edd581e83e 100644 (file)
@@ -33,7 +33,7 @@ static struct passwd *uname_string_combinations2(char *s, int offset, struct pas
 
 BOOL name_is_local(const char *name)
 {
-       return !strchr_m(name, *lp_winbind_separator());
+       return !(strchr_m(name, *lp_winbind_separator()) || lp_winbind_use_default_domain());
 }
 
 /****************************************************************************
index 92236838547eb822580fa471dbc07cdf3ea69598..f95ee89a29c156d0eafdd9d6ca49ee8f3a7cefaa 100644 (file)
@@ -509,8 +509,8 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
  **/
 
 NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                       char *username, char *domain, char *workstation, 
-                                       uint8 chal[8],
+                                       const char *username, const char *domain, const char *workstation, 
+                                       const uint8 chal[8],
                                        DATA_BLOB lm_response, DATA_BLOB nt_response,
                                        NET_USER_INFO_3 *info3)
 
@@ -554,7 +554,7 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c
        init_id_info2(&ctr.auth.id2, domain,
                      0, /* param_ctrl */
                      0xdead, 0xbeef, /* LUID? */
-                     username, workstation_name_slash, (uchar*)chal,
+                     username, workstation_name_slash, (const uchar*)chal,
                      lm_response.data, lm_response.length, nt_response.data, nt_response.length);
  
         init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname,
index 7bfa65176c7f81e008c9d35e7621463c30164a0e..04734c7f8e5571036c21ec56c06d1d5a05464891 100644 (file)
@@ -32,21 +32,47 @@ NSS_STATUS winbindd_request(int req_type,
 
 /* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the
    form DOMAIN/user into a domain and a user */
+extern fstring global_myworkgroup;
 
 static BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
 {
        char *p = strchr(domuser,*lp_winbind_separator());
 
-       if (!p)
+       if (!(p || lp_winbind_use_default_domain()))
                return False;
-        
-       fstrcpy(user, p+1);
-       fstrcpy(domain, domuser);
-       domain[PTR_DIFF(p, domuser)] = 0;
+       
+       if(!p && lp_winbind_use_default_domain()) {
+               fstrcpy(user, domuser);
+               fstrcpy(domain, global_myworkgroup);
+       } else {
+               fstrcpy(user, p+1);
+               fstrcpy(domain, domuser);
+               domain[PTR_DIFF(p, domuser)] = 0;
+       }
        strupper(domain);
        return True;
 }
 
+/*
+     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
+     'winbind separator' options.
+     This means:
+       - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
+       global_myworkgroup
+        
+*/
+static void fill_domain_username(fstring name, const char *domain, const char *user)
+{
+       if(lp_winbind_use_default_domain() &&
+           !strcmp(global_myworkgroup, domain)) {
+               strlcpy(name, user, sizeof(fstring));
+       } else {
+               slprintf(name, sizeof(fstring) - 1, "%s%s%s",
+                        domain, lp_winbind_separator(),
+                        user);
+       }
+}
+
 /* Call winbindd to convert a name to a sid */
 
 BOOL winbind_lookup_name(const char *name, DOM_SID *sid, 
@@ -60,10 +86,11 @@ BOOL winbind_lookup_name(const char *name, DOM_SID *sid,
                return False;
 
        /*
-        * Don't do the lookup if the name has no separator.
+        * Don't do the lookup if the name has no separator _and_ we are not in
+        * 'winbind use default domain' mode.
         */
 
-       if (!strchr(name, *lp_winbind_separator()))
+       if (!(strchr(name, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
                return False;
 
        /* Send off request */
@@ -291,7 +318,7 @@ int winbind_initgroups(char *user, gid_t gid)
 
        /* Call normal initgroups if we are a local user */
 
-       if (!strchr(user, *lp_winbind_separator())) {
+       if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain())) {
                return initgroups(user, gid);
        }
 
@@ -337,11 +364,17 @@ int winbind_initgroups(char *user, gid_t gid)
                }
 
        } else {
-               
-               /* The call failed.  Set errno to something so we don't get
-                  a bogus value from the last failed system call. */
-
-               errno = EIO;
+               /* The call failed but if 'winbind use default domain' is 'true', we
+                   should call normal initgroups. */
+                   
+               if (lp_winbind_use_default_domain()) {
+                       return initgroups(user, gid);
+               } else {
+                       /* The call failed.  Set errno to something so we don't get
+                          a bogus value from the last failed system call. */
+
+                       errno = EIO;
+               }
        }
 
        /* Free response data if necessary */
@@ -363,10 +396,11 @@ int winbind_getgroups(const char *user, int size, gid_t *list)
        int result, i;
 
        /*
-        * Don't do the lookup if the name has no separator.
+        * Don't do the lookup if the name has no separator _and_ we are not in
+        * 'winbind use default domain' mode.
         */
 
-       if (!strchr(user, *lp_winbind_separator()))
+       if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
                return -1;
 
        /* Fetch list of groups */
@@ -410,8 +444,7 @@ BOOL winbind_uidtoname(fstring name, uid_t uid)
        if (name_type != SID_NAME_USER)
                return False;
 
-       slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, 
-                 lp_winbind_separator(), user_name);
+       fill_domain_username(name, dom_name, user_name);
 
        return True;
 }
@@ -433,8 +466,7 @@ BOOL winbind_gidtoname(fstring name, gid_t gid)
        if (name_type != SID_NAME_DOM_GRP)
                return False;
 
-       slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, 
-                 lp_winbind_separator(), group_name);
+       fill_domain_username(name, dom_name, group_name);
 
        return True;
 }
index ab5d98bf9e569e7581eb21cb0753c74190fa780a..c6a0b040cbd1147a86b2d3bd71d4f34a5630049a 100644 (file)
@@ -66,8 +66,11 @@ static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain, fstrin
 
        char *p = strchr(domuser,get_winbind_separator());
 
-       if (!p)
-               return False;
+       if (!p) {
+               fstrcpy(user, domuser);
+               domain[0]=0;
+               return True;
+       }
         
        fstrcpy(user, p+1);
        fstrcpy(domain, domuser);
@@ -361,17 +364,11 @@ static BOOL wbinfo_auth_crap(char *username)
         fstring name_domain;
         fstring pass;
         char *p;
-       char sep = get_winbind_separator();
 
        /*
         * Don't do the lookup if the name has no separator.
         */
  
-       if (!strchr(username, sep)) {
-               printf("no domain seperator (%c) in username - failing\n", sep);
-               return False;
-       }
-
        /* Send off request */
 
        ZERO_STRUCT(request);
index cd4254acfccdf40c8ddbe8ec9fe9bfd11002abf7..a70f94781ef5d0fadbfbe3f55884ffb1b77f243c 100644 (file)
@@ -128,8 +128,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
 
                /* Append domain name */
 
-               snprintf(name, sizeof(name), "%s%s%s", domain->name,
-                        lp_winbind_separator(), the_name);
+               fill_domain_username(name, domain->name, the_name);
 
                len = strlen(name);
                
@@ -299,6 +298,7 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
        if (strcmp(lp_winbind_separator(),"\\"))
                string_sub(group_name, "\\", lp_winbind_separator(), 
                           sizeof(fstring));
+       strip_domain_name_if_needed(&group_name);
 
        if (!((name_type == SID_NAME_ALIAS) || 
              (name_type == SID_NAME_DOM_GRP))) {
@@ -558,10 +558,9 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
                
                /* Fill in group entry */
 
-               slprintf(domain_group_name, sizeof(domain_group_name) - 1,
-                        "%s%s%s", ent->domain_name, lp_winbind_separator(), 
+               fill_domain_username(domain_group_name, ent->domain_name, 
                         name_list[ent->sam_entry_index].acct_name);
-   
+
                result = fill_grent(&group_list[group_list_ndx], 
                                    domain_group_name, group_gid);
 
@@ -732,8 +731,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
                                            groups.sam_entries)[i].acct_name; 
                        fstring name;
 
-                       snprintf(name, sizeof(name), "%s%s%s", domain->name, 
-                               lp_winbind_separator(), group_name);
+                       fill_domain_username(name, domain->name, group_name);
 
                        /* Append to extra data */                      
                        memcpy(&extra_data[extra_data_len], name, 
index 95f0d527bbe92481dc9bdd9f366ecb1aca007247..87c5d0fb4b39cd4a0411d80886f7d648d7f3d535 100644 (file)
@@ -56,7 +56,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
        
        if (!parse_domain_user(state->request.data.auth.user, name_domain, 
                               name_user)) {
-               DEBUG(5,("no domain seperator (%s) in username (%s) - failing fauth\n", lp_winbind_separator(), state->request.data.auth.user));
+               DEBUG(5,("no domain seperator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user));
                talloc_destroy(mem_ctx);
                return WINBINDD_ERROR;
        }
@@ -131,6 +131,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
         NET_USER_INFO_3 info3;
         struct cli_state *cli = NULL;
        TALLOC_CTX *mem_ctx;
+       const char *domain = NULL;
 
        DATA_BLOB lm_resp, nt_resp;
 
@@ -144,6 +145,22 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                return WINBINDD_ERROR;
        }
 
+       if (*state->request.data.auth_crap.domain) {
+               domain = talloc_strdup(mem_ctx, state->request.data.auth_crap.domain);
+       } else if (lp_winbind_use_default_domain()) {
+               domain = talloc_strdup(mem_ctx, lp_workgroup());
+       } else {
+               DEBUG(5,("no domain specified with username (%s) - failing auth\n", state->request.data.auth.user));
+               talloc_destroy(mem_ctx);
+               return WINBINDD_ERROR;
+       }
+
+       if (!domain) {
+               DEBUG(0,("winbindd_pam_auth_crap: talloc_strdup failed!\n"));
+               talloc_destroy(mem_ctx);
+               return WINBINDD_ERROR;
+       }
+
        lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len);
        nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
        
@@ -169,7 +186,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
         }
 
        result = cli_netlogon_sam_network_logon(cli, mem_ctx,
-                                               state->request.data.auth_crap.user, state->request.data.auth_crap.domain, 
+                                               state->request.data.auth_crap.user, domain,
                                                global_myname, state->request.data.auth_crap.chal, 
                                                lm_resp, nt_resp, 
                                                &info3);
index bfadcc9a6c0d95a76a44c9b1f730f48ae478b4a1..565c08f549c2fd6c2324d1cc84f6d885d55582be 100644 (file)
@@ -117,4 +117,6 @@ void free_getent_state(struct getent_state *state);
 BOOL winbindd_param_init(void);
 BOOL check_domain_env(char *domain_env, char *domain);
 BOOL parse_domain_user(const char *domuser, fstring domain, fstring user);
+void strip_domain_name_if_needed(fstring *name);
+void fill_domain_username(fstring name, const char *domain, const char *user);
 #endif /* _PROTO_H_ */
index e5cacbb9897e7270d30d15d730dc04db437f134e..6a825c81f4ae300addeaa493d3969da106895857 100644 (file)
@@ -217,6 +217,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
        if (strcmp("\\", lp_winbind_separator()))
                string_sub(user_name, "\\", lp_winbind_separator(), 
                           sizeof(fstring));
+       strip_domain_name_if_needed(&user_name);
 
        /* Get some user info */
        
@@ -500,9 +501,8 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
 
                /* Lookup user info */
                
-               slprintf(domain_user_name, sizeof(domain_user_name) - 1,
-                        "%s%s%s", ent->domain_name, sep,
-                        name_list[ent->sam_entry_index].name);
+               fill_domain_username(domain_user_name, ent->domain_name, 
+                                    name_list[ent->sam_entry_index].name);
                
                result = winbindd_fill_pwent(
                        ent->domain_name, 
@@ -596,9 +596,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
                                fstrcpy(acct_name, info[i].acct_name);
                        }
                        
-                       slprintf(name, sizeof(name) - 1, "%s%s%s",
-                                domain->name, lp_winbind_separator(),
-                                acct_name);
+                       fill_domain_username(name, domain->name, acct_name);
                        
                                /* Append to extra data */
                        memcpy(&extra_data[extra_data_len], name, 
index f90e89c23f4b44733dcd16fa39ca55d4bb4e5171..640b581ce348f3b67581841c75a73a2f51c5012c 100644 (file)
@@ -348,17 +348,65 @@ BOOL check_domain_env(char *domain_env, char *domain)
 }
 
 /* Parse a string of the form DOMAIN/user into a domain and a user */
+extern fstring global_myworkgroup;
 
 BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
 {
        char *p = strchr(domuser,*lp_winbind_separator());
 
-       if (!p)
+       if (!(p || lp_winbind_use_default_domain()))
                return False;
        
-       fstrcpy(user, p+1);
-       fstrcpy(domain, domuser);
-       domain[PTR_DIFF(p, domuser)] = 0;
+       if(!p && lp_winbind_use_default_domain()) {
+               fstrcpy(user, domuser);
+               fstrcpy(domain, global_myworkgroup);
+       } else {
+               fstrcpy(user, p+1);
+               fstrcpy(domain, domuser);
+               domain[PTR_DIFF(p, domuser)] = 0;
+       }
        strupper(domain);
        return True;
 }
+
+/* 
+   Strip domain name if it is same as default domain name and 
+    winbind use default domain = true
+    
+   it assumes that name is actually fstring so that memory management
+   isn't needed.
+*/
+void strip_domain_name_if_needed(fstring *name)
+{
+       if(lp_winbind_use_default_domain()) {
+               char *sep = lp_winbind_separator();
+               char *new_name = strchr(*name, *sep);
+               if(new_name) {
+                       *new_name = 0;
+                       if (!strcmp(global_myworkgroup, *name)) {
+                           new_name++;
+                           safe_strcpy(*name, new_name, sizeof(fstring));
+                       } else *new_name = *sep;
+               }
+       }
+}
+
+/*
+    Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
+    'winbind separator' options.
+    This means:
+       - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
+       global_myworkgroup
+        
+*/
+void fill_domain_username(fstring name, const char *domain, const char *user)
+{
+       if(lp_winbind_use_default_domain() &&
+           !strcmp(global_myworkgroup, domain)) {
+               strlcpy(name, user, sizeof(fstring));
+       } else {
+               slprintf(name, sizeof(fstring) - 1, "%s%s%s",
+                        domain, lp_winbind_separator(),
+                        user);
+       }
+}
index d19d20f3f955c1f51e9e710be4e9f1ea33d60647..fce5fcde49885e9f6c3683b9ee483e1cefe1dfef 100644 (file)
@@ -155,6 +155,7 @@ typedef struct
        char *szWinbindSeparator;
        BOOL bWinbindEnumUsers;
        BOOL bWinbindEnumGroups;
+       BOOL bWinbindUseDefaultDomain;
        char *szAddShareCommand;
        char *szChangeShareCommand;
        char *szDeleteShareCommand;
@@ -1043,6 +1044,7 @@ static struct parm_struct parm_table[] = {
        {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, 0},
        {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, 0},
        {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, 0},
+       {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, 0},
 
        {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
 };
@@ -1368,6 +1370,7 @@ static void init_globals(void)
        Globals.winbind_cache_time = 15;
        Globals.bWinbindEnumUsers = True;
        Globals.bWinbindEnumGroups = True;
+       Globals.bWinbindUseDefaultDomain = False;
 
        Globals.bUseSpnego = True;
 
@@ -1511,6 +1514,7 @@ FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
 FN_GLOBAL_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
+FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
 #ifdef WITH_LDAP_SAM
 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)