1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-05 21:57:51 +03:00
samba-mirror/source/lib/username.c

325 lines
7.9 KiB
C
Raw Normal View History

/*
Unix SMB/Netbios implementation.
Version 1.9.
Username handling
'The mother of all checkins' :-). Jeremy Allison (jallison@whistle.com) Wed May 7 1997: Update for 1.9.17alpha1 release - 'browsefix release' designed to make browsing across subnets work. byteorder.h: Updated copyright to 1997. charcnv.c: Updated copyright to 1997. charset.c Updated copyright to 1997. charset.h Updated copyright to 1997. client.c Updated copyright to 1997. clientutil.c Updated copyright to 1997. dir.c Updated copyright to 1997. fault.c Updated copyright to 1997. includes.h Updated copyright to 1997. interface.c Updated copyright to 1997. ipc.c Updated copyright to 1997. kanji.c Updated copyright to 1997. kanji.h Updated copyright to 1997. loadparm.c Updated copyright to 1997. locking.c Updated copyright to 1997. mangle.c Updated copyright to 1997. message.c Updated copyright to 1997. nameannounce.c Made use of WINS subnet explicit. Added reset_announce_timer() so announcement can be made immediately when we become a master. Expanded code to do sync with dmb. namebrowse.c Removed redundent checks for AM_MASTER in sync code. Made use of WINS subnet explicit. namedbname.c Made use of WINS subnet explicit. namedbresp.c Made use of WINS subnet explicit. namedbserver.c Made use of WINS subnet explicit. namedbsubnet.c Explicitly add workgroup to WINS subnet when we become a dmb. Made use of WINS subnet explicit. namedbwork.c Made use of WINS subnet explicit. Removed redundent check_work_servertype() function. nameelect.c Explicitly add workgroup to WINS subnet when we become a master browser. Made use of WINS subnet explicit. namelogon.c Updated copyright to 1997. namepacket.c Updated copyright to 1997. namequery.c Updated copyright to 1997. nameresp.c Made use of WINS subnet explicit. Made nmbd fail if configured as master browser and one exists already. nameserv.c Made use of WINS subnet explicit. Remove redundent logon server and domain master code. nameserv.h Add emumerate subnet macros. nameservreply.c Made use of WINS subnet explicit. nameservresp.c Updated copyright to 1997. namework.c Made use of WINS subnet explicit. Updated code to add sync browser entries to add subnet parameter. nmbd.c Added sanity check for misconfigured nmbd. nmblib.c Updated copyright to 1997. nmblookup.c Updated copyright to 1997. nmbsync.c Removed redundent AM_ANY_MASTER check. params.c Updated copyright to 1997. password.c Updated copyright to 1997. pipes.c Updated copyright to 1997. predict.c Updated copyright to 1997. printing.c Updated copyright to 1997. proto.h Changed protos for new nmbd code. quotas.c Updated copyright to 1997. replace.c Updated copyright to 1997. reply.c Updated copyright to 1997. server.c Updated copyright to 1997. shmem.c Updated copyright to 1997. smb.h Updated copyright to 1997. smbencrypt.c Updated copyright to 1997. smbpasswd.c Updated copyright to 1997. smbrun.c Updated copyright to 1997. status.c Updated copyright to 1997. system.c Updated copyright to 1997. testparm.c Updated copyright to 1997. testprns.c Updated copyright to 1997. time.c Updated copyright to 1997. trans2.c Updated copyright to 1997. trans2.h Updated copyright to 1997. uid.c Updated copyright to 1997. username.c Updated copyright to 1997. util.c Updated copyright to 1997. version.h Changed to 1.9.17alpha1.
-
Copyright (C) Andrew Tridgell 1992-1997
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
extern int DEBUGLEVEL;
/* internal functions - modified versions of the ones in password.c */
static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (), int N);
static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (), int N);
/****************************************************************************
get a users home directory. tries as-is then lower case
****************************************************************************/
char *get_home_dir(char *user)
{
static struct passwd *pass;
pass = Get_Pwnam(user,False);
if (!pass) return(NULL);
return(pass->pw_dir);
}
/*******************************************************************
map a username from a dos name to a unix name by looking in the username
map
********************************************************************/
void map_username(char *user)
{
static int depth=0;
static BOOL initialised=False;
static fstring last_from,last_to;
FILE *f;
char *s;
char *mapfile = lp_username_map();
if (!*mapfile || depth) return;
if (!*user) return;
if (!initialised) {
*last_from = *last_to = 0;
initialised = True;
}
if (strequal(user,last_to)) return;
if (strequal(user,last_from)) {
DEBUG(3,("Mapped user %s to %s\n",user,last_to));
fstrcpy(user,last_to);
return;
}
f = fopen(mapfile,"r");
if (!f) {
DEBUG(0,("can't open username map %s\n",mapfile));
return;
}
DEBUG(4,("Scanning username map %s\n",mapfile));
depth++;
for (; (s=fgets_slash(NULL,80,f)); free(s)) {
char *unixname = s;
char *dosname = strchr(unixname,'=');
if (!dosname) continue;
*dosname++ = 0;
while (isspace(*unixname)) unixname++;
if (!*unixname || strchr("#;",*unixname)) continue;
{
int l = strlen(unixname);
while (l && isspace(unixname[l-1])) {
unixname[l-1] = 0;
l--;
}
}
if (strchr(dosname,'*') || user_in_list(user,dosname)) {
DEBUG(3,("Mapped user %s to %s\n",user,unixname));
StrnCpy(last_from,user,sizeof(last_from)-1);
sscanf(unixname,"%s",user);
StrnCpy(last_to,user,sizeof(last_to)-1);
}
}
fclose(f);
depth--;
}
/****************************************************************************
internals of Get_Pwnam wrapper
****************************************************************************/
static struct passwd *_Get_Pwnam(char *s)
{
struct passwd *ret;
ret = getpwnam(s);
if (ret)
{
#ifdef GETPWANAM
struct passwd_adjunct *pwret;
pwret = getpwanam(s);
if (pwret)
{
free(ret->pw_passwd);
ret->pw_passwd = pwret->pwa_passwd;
}
#endif
}
return(ret);
}
/****************************************************************************
a wrapper for getpwnam() that tries with all lower and all upper case
if the initial name fails. Also tried with first letter capitalised
Note that this changes user!
****************************************************************************/
struct passwd *Get_Pwnam(char *user,BOOL allow_change)
{
fstring user2;
int last_char;
int usernamelevel = lp_usernamelevel();
struct passwd *ret;
if (!user || !(*user))
return(NULL);
StrnCpy(user2,user,sizeof(user2)-1);
if (!allow_change) {
user = &user2[0];
}
map_username(user);
ret = _Get_Pwnam(user);
if (ret) return(ret);
strlower(user);
ret = _Get_Pwnam(user);
if (ret) return(ret);
strupper(user);
ret = _Get_Pwnam(user);
if (ret) return(ret);
/* try with first letter capitalised */
if (strlen(user) > 1)
strlower(user+1);
ret = _Get_Pwnam(user);
if (ret) return(ret);
/* try with last letter capitalised */
strlower(user);
last_char = strlen(user)-1;
user[last_char] = toupper(user[last_char]);
DEBUG(3, ("Trying username %s\n", user));
ret = _Get_Pwnam(user);
if (ret) return(ret);
/* try all combinations up to usernamelevel */
strlower(user);
ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
if (ret) return(ret);
if (allow_change)
fstrcpy(user,user2);
return(NULL);
}
/****************************************************************************
check if a user is in a user list
****************************************************************************/
BOOL user_in_list(char *user,char *list)
{
pstring tok;
char *p=list;
while (next_token(&p,tok,LIST_SEP))
{
if (strequal(user,tok))
return(True);
#ifdef NETGROUP
if (*tok == '@')
{
static char *mydomain = NULL;
if (mydomain == 0)
yp_get_default_domain(&mydomain);
if(mydomain == 0)
{
DEBUG(5,("Unable to get default yp domain\n"));
}
else
{
DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
user, mydomain, &tok[1]));
DEBUG(5,("innetgr is %s\n",
innetgr(&tok[1], (char *) 0, user, mydomain)
? "TRUE" : "FALSE"));
if (innetgr(&tok[1], (char *)0, user, mydomain))
return (True);
}
}
#endif
#if HAVE_GETGRNAM
if (*tok == '@')
{
struct group *gptr;
char **member;
struct passwd *pass = Get_Pwnam(user,False);
if (pass) {
gptr = getgrgid(pass->pw_gid);
if (gptr && strequal(gptr->gr_name,&tok[1]))
return(True);
}
gptr = (struct group *)getgrnam(&tok[1]);
if (gptr)
{
member = gptr->gr_mem;
while (member && *member)
{
if (strequal(*member,user))
return(True);
member++;
}
}
}
#endif
}
return(False);
}
/* The functions below have been taken from password.c and slightly modified */
/****************************************************************************
apply a function to upper/lower case combinations
of a string and return true if one of them returns true.
try all combinations with N uppercase letters.
offset is the first char to try and change (start with 0)
it assumes the string starts lowercased
****************************************************************************/
static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(),int N)
{
int len = strlen(s);
int i;
struct passwd *ret;
#ifdef PASSWORD_LENGTH
len = MIN(len,PASSWORD_LENGTH);
#endif
if (N <= 0 || offset >= len)
return(fn(s));
for (i=offset;i<(len-(N-1));i++)
{
char c = s[i];
if (!islower(c)) continue;
s[i] = toupper(c);
ret = uname_string_combinations2(s,i+1,fn,N-1);
if(ret) return(ret);
s[i] = c;
}
return(NULL);
}
/****************************************************************************
apply a function to upper/lower case combinations
of a string and return true if one of them returns true.
try all combinations with up to N uppercase letters.
offset is the first char to try and change (start with 0)
it assumes the string starts lowercased
****************************************************************************/
static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(),int N)
{
int n;
struct passwd *ret;
for (n=1;n<=N;n++)
{
ret = uname_string_combinations2(s,0,fn,n);
if(ret) return(ret);
}
return(NULL);
}