1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/source3/smbd/uid.c
Andrew Tridgell a2c1623827 a huge pile of changes :-)
The biggest thing is the integration of Lukes new nmbd. Its still
largely untested, so we will really need some feedback

I've also added auto prototype generation and cleaned up a lot of
minor things as a result
(This used to be commit 0d8dcfa13c)
1996-06-04 06:42:03 +00:00

361 lines
9.0 KiB
C

/*
Unix SMB/Netbios implementation.
Version 1.9.
uid/user handling
Copyright (C) Andrew Tridgell 1992-1995
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"
#include "loadparm.h"
extern int DEBUGLEVEL;
extern connection_struct Connections[];
static int initial_uid;
static int initial_gid;
static int old_umask = 022;
static pstring OriginalDir;
/* what user is current? */
struct current_user current_user;
/****************************************************************************
initialise the uid routines
****************************************************************************/
void init_uid(void)
{
initial_uid = current_user.uid = geteuid();
initial_gid = current_user.gid = getegid();
if (initial_gid != 0 && initial_uid == 0)
{
#ifdef HPUX
setresgid(0,0,0);
#else
setgid(0);
setegid(0);
#endif
}
initial_uid = geteuid();
initial_gid = getegid();
current_user.cnum = -1;
GetWd(OriginalDir);
}
/****************************************************************************
become the specified uid
****************************************************************************/
static BOOL become_uid(int uid)
{
if (initial_uid != 0)
return(True);
#ifdef AIX
{
/* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
priv_t priv;
priv.pv_priv[0] = 0;
priv.pv_priv[1] = 0;
if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
&priv, sizeof(priv_t)) < 0 ||
setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 ||
seteuid((uid_t)uid) < 0)
DEBUG(1,("Can't set uid (AIX3)"));
}
#endif
#ifdef USE_SETRES
if (setresuid(-1,uid,-1) != 0)
#elif defined(USE_SETFS)
if (setfsuid(uid) != 0)
#else
if ((seteuid(uid) != 0) &&
(setuid(uid) != 0))
#endif
{
DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
uid,getuid(), geteuid()));
if (uid > 32000)
DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
return(False);
}
if (((uid == -1) || (uid == 65535)) && geteuid() != uid) {
DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
return(False);
}
current_user.uid = uid;
return(True);
}
/****************************************************************************
become the specified gid
****************************************************************************/
static BOOL become_gid(int gid)
{
if (initial_uid != 0)
return(True);
#ifdef USE_SETRES
if (setresgid(-1,gid,-1) != 0)
#elif defined(USE_SETFS)
if (setfsgid(gid) != 0)
#else
if (setgid(gid) != 0)
#endif
{
DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
gid,getgid(),getegid()));
if (gid > 32000)
DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
return(False);
}
current_user.gid = gid;
return(True);
}
/****************************************************************************
become the specified uid and gid
****************************************************************************/
static BOOL become_id(int uid,int gid)
{
return(become_gid(gid) && become_uid(uid));
}
/****************************************************************************
become the guest user
****************************************************************************/
BOOL become_guest(void)
{
BOOL ret;
static struct passwd *pass=NULL;
if (initial_uid != 0)
return(True);
if (!pass)
pass = Get_Pwnam(lp_guestaccount(-1),True);
if (!pass) return(False);
ret = become_id(pass->pw_uid,pass->pw_gid);
if (!ret)
DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
current_user.cnum = -2;
return(ret);
}
/*******************************************************************
check if a username is OK
********************************************************************/
static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
{
int i;
for (i=0;i<Connections[cnum].uid_cache.entries;i++)
if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True);
if (!user_ok(vuser->name,snum)) return(False);
i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
Connections[cnum].uid_cache.list[i] = vuser->uid;
if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
Connections[cnum].uid_cache.entries++;
return(True);
}
/****************************************************************************
become the user of a connection number
****************************************************************************/
BOOL become_user(int cnum, int uid)
{
int new_umask;
user_struct *vuser;
int snum,gid;
int id = uid;
if (current_user.cnum == cnum && current_user.id == id) {
DEBUG(4,("Skipping become_user - already user\n"));
return(True);
}
unbecome_user();
if (!OPEN_CNUM(cnum)) {
DEBUG(2,("Connection %d not open\n",cnum));
return(False);
}
snum = Connections[cnum].service;
if (Connections[cnum].force_user ||
lp_security() == SEC_SHARE ||
!(vuser = get_valid_user_struct(uid)) ||
!check_user_ok(cnum,vuser,snum)) {
uid = Connections[cnum].uid;
gid = Connections[cnum].gid;
current_user.groups = Connections[cnum].groups;
current_user.igroups = Connections[cnum].igroups;
current_user.ngroups = Connections[cnum].ngroups;
} else {
if (!vuser) {
DEBUG(2,("Invalid vuid used %d\n",uid));
return(False);
}
uid = vuser->uid;
if(!*lp_force_group(snum))
gid = vuser->gid;
else
gid = Connections[cnum].gid;
current_user.groups = vuser->user_groups;
current_user.igroups = vuser->user_igroups;
current_user.ngroups = vuser->user_ngroups;
}
if (initial_uid == 0)
{
if (!become_gid(gid)) return(False);
#ifndef NO_SETGROUPS
if (!IS_IPC(cnum)) {
/* groups stuff added by ih/wreu */
if (current_user.ngroups > 0)
if (setgroups(current_user.ngroups,current_user.groups)<0)
DEBUG(0,("setgroups call failed!\n"));
}
#endif
if (!Connections[cnum].admin_user && !become_uid(uid))
return(False);
}
new_umask = 0777 & ~CREATE_MODE(cnum);
old_umask = umask(new_umask);
current_user.cnum = cnum;
current_user.id = id;
DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
getuid(),geteuid(),getgid(),getegid(),new_umask));
return(True);
}
/****************************************************************************
unbecome the user of a connection number
****************************************************************************/
BOOL unbecome_user(void )
{
if (current_user.cnum == -1)
return(False);
ChDir(OriginalDir);
umask(old_umask);
if (initial_uid == 0)
{
#ifdef USE_SETRES
setresuid(-1,getuid(),-1);
setresgid(-1,getgid(),-1);
#elif defined(USE_SETFS)
setfsuid(initial_uid);
setfsgid(initial_gid);
#else
if (seteuid(initial_uid) != 0)
setuid(initial_uid);
setgid(initial_gid);
#endif
}
#ifdef NO_EID
if (initial_uid == 0)
DEBUG(2,("Running with no EID\n"));
initial_uid = getuid();
initial_gid = getgid();
#else
if (geteuid() != initial_uid)
{
DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
initial_uid = geteuid();
}
if (getegid() != initial_gid)
{
DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
initial_gid = getegid();
}
#endif
current_user.uid = initial_uid;
current_user.gid = initial_gid;
if (ChDir(OriginalDir) != 0)
DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
timestring(),OriginalDir));
DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
getuid(),geteuid(),getgid(),getegid()));
current_user.cnum = -1;
return(True);
}
/****************************************************************************
run a command via system() using smbrun, being careful about uid/gid handling
****************************************************************************/
int smbrun(char *cmd,char *outfile)
{
int ret;
pstring syscmd;
char *path = lp_smbrun();
if (!file_exist(path,NULL))
{
DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",path));
return(1);
}
sprintf(syscmd,"%s %d %d \"(%s 2>&1) > %s\"",
path,current_user.uid,current_user.gid,cmd,
outfile?outfile:"/dev/null");
DEBUG(5,("smbrun - running %s ",syscmd));
ret = system(syscmd);
DEBUG(5,("gave %d\n",ret));
return(ret);
}