From 1fb9ccc4e2a91bf7124fba076ffa5458a1cbf404 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jan 2002 02:37:55 +0000 Subject: This is the 'winbind default domain' patch from Alexander Bokovoy . 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) --- docs/docbook/manpages/smb.conf.5.sgml | 19 +++++++++- docs/docbook/manpages/winbindd.8.sgml | 14 +++++++ source3/lib/username.c | 2 +- source3/libsmb/cli_netlogon.c | 6 +-- source3/nsswitch/wb_client.c | 70 +++++++++++++++++++++++++---------- source3/nsswitch/wbinfo.c | 13 +++---- source3/nsswitch/winbindd_group.c | 12 +++--- source3/nsswitch/winbindd_pam.c | 21 ++++++++++- source3/nsswitch/winbindd_proto.h | 2 + source3/nsswitch/winbindd_user.c | 10 ++--- source3/nsswitch/winbindd_util.c | 56 ++++++++++++++++++++++++++-- source3/param/loadparm.c | 4 ++ 12 files changed, 178 insertions(+), 51 deletions(-) diff --git a/docs/docbook/manpages/smb.conf.5.sgml b/docs/docbook/manpages/smb.conf.5.sgml index 9e719e1f2a..7aa9ea3b9c 100644 --- a/docs/docbook/manpages/smb.conf.5.sgml +++ b/docs/docbook/manpages/smb.conf.5.sgml @@ -762,6 +762,7 @@ winbind gid winbind separator winbind uid + winbind use default domain wins hook wins proxy wins server @@ -8195,7 +8196,23 @@ veto files = /.AppleDouble/.bin/.AppleDesktop/Network Trash Folder/ - + + winbind use default domain + + + winbind use default domain + This parameter specifies whether the + winbindd(8) + 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. + + Default: winbind use default domain = <falseg> + + Example: winbind use default domain = true + + diff --git a/docs/docbook/manpages/winbindd.8.sgml b/docs/docbook/manpages/winbindd.8.sgml index af851657f3..bd1dafa07e 100644 --- a/docs/docbook/manpages/winbindd.8.sgml +++ b/docs/docbook/manpages/winbindd.8.sgml @@ -276,6 +276,20 @@ group: files winbind Default: template shell = /bin/false + + + winbind use default domain + This parameter specifies whether the winbindd + 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. + + Default: winbind use default domain = <falseg> + + Example: winbind use default domain = true + + diff --git a/source3/lib/username.c b/source3/lib/username.c index 9541ebeb08..7c8c9c740d 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -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()); } /**************************************************************************** diff --git a/source3/libsmb/cli_netlogon.c b/source3/libsmb/cli_netlogon.c index 9223683854..f95ee89a29 100644 --- a/source3/libsmb/cli_netlogon.c +++ b/source3/libsmb/cli_netlogon.c @@ -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, diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index 7bfa65176c..04734c7f8e 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/nsswitch/wb_client.c @@ -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; } diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index ab5d98bf9e..c6a0b040cb 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -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); diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index cd4254acfc..a70f94781e 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -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, diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 95f0d527bb..87c5d0fb4b 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -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); diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index bfadcc9a6c..565c08f549 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -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_ */ diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index e5cacbb989..6a825c81f4 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -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, diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index f90e89c23f..640b581ce3 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -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); + } +} diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index d19d20f3f9..fce5fcde49 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -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) -- cgit