1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-22 05:57:43 +03:00

- moved the uid handling to uid.c

- added setfsuid() support (for Linux)
- started adding some of Lukes changes, just the loadparm and ipc ones
so far
(This used to be commit 72543810ce3eb5ea7b141f957edf38b4c46b1ea4)
This commit is contained in:
Andrew Tridgell 1996-06-01 15:25:30 +00:00
parent 0966bf7fb7
commit 81e398963d
9 changed files with 549 additions and 435 deletions

View File

@ -223,6 +223,7 @@ Here come some platform specific sections
#define USE_SETSID
#define HAVE_BZERO
#define HAVE_MEMMOVE
#define USE_SETFS
#ifdef SHADOW_PWD
#ifndef crypt
#define crypt pw_encrypt

View File

@ -583,6 +583,8 @@ struct from_host {
};
/* and a few prototypes */
BOOL become_guest(void);
void init_uid(void);
BOOL user_ok(char *user,int snum);
int sys_rename(char *from, char *to);
int sys_select(fd_set *fds,struct timeval *tval);

View File

@ -3585,34 +3585,6 @@ int PutUniCode(char *dst,char *src)
return(ret);
}
pstring smbrun_path = SMBRUN;
/****************************************************************************
run a command via system() using smbrun
****************************************************************************/
int smbrun(char *cmd,char *outfile)
{
int ret;
pstring syscmd;
if (!file_exist(smbrun_path,NULL))
{
DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",smbrun_path));
return(1);
}
sprintf(syscmd,"%s \"(%s 2>&1) > %s\"",
smbrun_path,cmd,
outfile?outfile:"/dev/null");
DEBUG(5,("smbrun - running %s ",syscmd));
ret = system(syscmd);
DEBUG(5,("gave %d\n",ret));
return(ret);
}
/****************************************************************************
a wrapper for gethostbyname() that tries with all lower and all upper case
if the initial name fails
@ -3745,8 +3717,7 @@ my own panic function - not suitable for general use
********************************************************************/
void ajt_panic(void)
{
pstring cmd = "/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &";
smbrun(cmd,NULL);
system("/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &");
}
#endif

View File

@ -43,6 +43,7 @@ extern char *lp_guestaccount(int iService);
extern char *lp_printcapname(void);
extern char *lp_lockdir(void);
extern char *lp_logfile(void);
extern char *lp_smbrun(void);
extern char *lp_configfile(void);
extern char *lp_smb_passwd_file(void);
extern char *lp_rootdir(void);
@ -55,6 +56,7 @@ extern char *lp_domain_controller(void);
extern char *lp_username_map(void);
extern char *lp_hosts_equiv(void);
extern char *lp_logon_script(void);
extern char *lp_wins_server(void);
extern char *lp_magicscript(int iService);
extern char *lp_magicoutput(int iService);
extern char *lp_mangled_map(int iService);

View File

@ -58,7 +58,6 @@ BOOL bLoaded = False;
extern int DEBUGLEVEL;
extern int ReadSize;
extern pstring user_socket_options;
extern pstring smbrun_path;
#ifndef GLOBAL_NAME
#define GLOBAL_NAME "global"
@ -132,6 +131,8 @@ typedef struct
char *szUsernameMap;
char *szCharacterSet;
char *szLogonScript;
char *szWINSserver;
char *szSmbrun;
int max_log_size;
int mangled_stack;
int max_xmit;
@ -368,7 +369,7 @@ struct parm_struct
{"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
{"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
{"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
{"smbrun", P_GSTRING, P_GLOBAL, smbrun_path, NULL},
{"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
{"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
{"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
{"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
@ -395,6 +396,7 @@ struct parm_struct
{"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
{"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
{"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
{"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
{"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
{"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
{"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
@ -543,6 +545,7 @@ static void init_globals(void)
string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
string_set(&Globals.szLockDir, LOCKDIR);
string_set(&Globals.szRootdir, "/");
string_set(&Globals.szSmbrun, SMBRUN);
sprintf(s,"Samba %s",VERSION);
string_set(&Globals.szServerString,s);
Globals.bLoadPrinters = True;
@ -677,6 +680,7 @@ char *lp_string(char *s)
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
@ -696,6 +700,7 @@ FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)

View File

@ -751,44 +751,64 @@ struct srv_info_struct
filter out unwanted server info
******************************************************************/
static BOOL filter_server_info(struct srv_info_struct *server,
char *domain)
BOOL domains,
char *domain, uint32 request)
{
if (*domain)
return(strequal(domain, server->domain));
return (True); /* be indiscriminate: get all servers! */
}
/*******************************************************************
find server in the files saved by nmbd. Return True if we find it.
******************************************************************/
static BOOL find_server(struct srv_info_struct *servers, int num_servers,
char *domain, char *name)
{
int count;
if (!servers || num_servers == 0) return (False);
for (count = 0; count < num_servers; count++) {
struct srv_info_struct *s;
s = &servers[count];
if (strequal(name, s->name)) {
StrnCpy(domain, s->domain, sizeof(pstring)-1);
return (True);
if (*domain == 0)
{
if (strequal(lp_workgroup(), server->domain)) {
return True;
}
else if (domains)
{
DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
return False;
}
else if ((request & SV_TYPE_DOMAIN_ENUM) &&
(server->type & SV_TYPE_DOMAIN_ENUM))
{
DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
return False;
}
return True;
}
else
{
if (strequal(domain, server->domain))
{
/*
if (request == SV_TYPE_LOCAL_LIST_ONLY &&
!(server->type & SV_TYPE_LOCAL_LIST_ONLY))
{
DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
return False;
}
*/
if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
!(server->type&SV_TYPE_DOMAIN_ENUM))
{
DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
return False;
}
return True;
}
else if (!domains)
{
DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
return False;
}
return True;
}
}
return (False);
}
/*******************************************************************
get server info lists from the files saved by nmbd. Return the
number of entries
******************************************************************/
static int get_server_info(uint32 servertype,
struct srv_info_struct **servers)
struct srv_info_struct **servers, BOOL domains, char *domain)
{
FILE *f;
pstring fname;
@ -807,18 +827,23 @@ static int get_server_info(uint32 servertype,
DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
return(0);
}
/* request for everything is code for request all servers */
if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
DEBUG(4, ("Servertype search: %8x domains:%s\n", servertype,BOOLSTR(domains)));
while (!feof(f))
{
fstring stype;
struct srv_info_struct *s;
char *ptr = line;
BOOL ok = True;
*ptr = 0;
fgets(line,sizeof(line)-1,f);
if (!*line) continue;
if (count == alloced) {
alloced += 10;
(*servers) = (struct srv_info_struct *)
@ -827,32 +852,52 @@ static int get_server_info(uint32 servertype,
bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
}
s = &(*servers)[count];
s->server_added = True;
if (!next_token(&ptr,s->name , NULL)) continue;
if (!next_token(&ptr,stype , NULL)) continue;
if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) {
/* this allows us to cop with an old nmbd */
/* this allows us to cope with an old nmbd */
strcpy(s->domain,my_workgroup());
}
if (sscanf(stype,"%X",&s->type) != 1) continue;
if (sscanf(stype,"%X",&s->type) != 1) { DEBUG(4,("r:host file ")); ok = False; }
/* doesn't match up: don't want it */
if (!(servertype & s->type)) continue;
/* server entry is a domain, we haven't asked for domains: don't want it */
if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM))
continue;
DEBUG(4,("Server %20s %8x %25s %15s\n",
s->name, stype, s->comment, s->domain));
count++;
if (!(servertype & s->type)) { DEBUG(4,("r:serv type ")); ok = False; }
if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
(s->type & SV_TYPE_DOMAIN_ENUM))
{
DEBUG(4,("s:all x dom "));
ok = False;
}
if (domains && !(domain && *domain && strequal(domain, s->domain)))
{
if (!(s->type & SV_TYPE_DOMAIN_ENUM))
{
DEBUG(4,("r:dom enum "));
ok = False;
}
}
if (ok)
{
DEBUG(4,("**SV** %20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
s->type |= SV_TYPE_LOCAL_LIST_ONLY;
s->server_added = True;
count++;
}
else
{
DEBUG(4,("%20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
}
}
fclose(f);
return(count);
}
@ -957,8 +1002,14 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
int counted=0,total=0;
int i;
fstring domain;
BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) &&
!(servertype == SV_TYPE_ALL);
BOOL domains;
BOOL domain_request;
BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
/*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
domain[0] = 0;
p += 8;
@ -966,49 +1017,46 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
if (!prefix_ok(str1,"WrLehD")) return False;
if (!check_server_info(uLevel,str2)) return False;
DEBUG(4, ("server request level: %s\n", str2));
DEBUG(4, ("server request level: %s %8x ", str2, servertype));
DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
if (strcmp(str1, "WrLehDO") == 0)
{
/* asking for servers. we will have to work out which workgroup was
requested, as we maintain lists for multiple workgroups */
domains = False;
}
else if (strcmp(str1, "WrLehDz") == 0)
{
/* asking for a specific workgroup */
domains = True;
StrnCpy(domain, p, sizeof(fstring)-1);
}
if (lp_browse_list())
{
total = get_server_info(servertype,&servers);
}
if (!domain[0] && !domain_request) {
extern fstring remote_machine;
/* must be a server request with an assumed domain. find a domain */
if (find_server(servers, total, domain, remote_machine)) {
DEBUG(4, ("No domain specified: using %s for %s\n",
domain, remote_machine));
} else {
/* default to soemthing sensible */
strcpy(domain,my_workgroup());
}
total = get_server_info(servertype,&servers,domains,domain);
}
data_len = fixed_len = string_len = 0;
for (i=0;i<total;i++)
if (filter_server_info(&servers[i],domain)) {
data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0);
if (data_len <= buf_len)
{
counted++;
fixed_len += f_len;
string_len += s_len;
}
{
for (i=0;i<total;i++)
{
struct srv_info_struct *s = &servers[i];
if (filter_server_info(s,domains,domain,local_request|domain_request))
{
data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
if (data_len <= buf_len)
{
counted++;
fixed_len += f_len;
string_len += s_len;
}
}
}
}
*rdata_len = fixed_len + string_len;
*rdata = REALLOC(*rdata,*rdata_len);
@ -1021,10 +1069,15 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
{
int count2 = counted;
for (i = 0; i < total && count2;i++) {
if (filter_server_info(&servers[i],domain)) {
fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata);
count2--;
for (i = 0; i < total && count2;i++)
{
struct srv_info_struct *s = &servers[i];
if (filter_server_info(s,domains,domain,local_request|domain_request))
{
fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
count2--;
}
}
}
@ -1657,7 +1710,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
strcpy(comment,lp_serverstring());
if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) {
if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
for (i=0;i<count;i++)
if (strequal(servers[i].name,local_machine)) {
servertype = servers[i].type;

View File

@ -26,7 +26,6 @@
#include "reply.h"
pstring servicesf = CONFIGFILE;
pstring OriginalDir ="/";
extern pstring debugf;
extern pstring sesssetup_user;
@ -34,16 +33,8 @@ char *InBuffer = NULL;
char *OutBuffer = NULL;
char *last_inbuf = NULL;
int initial_uid = 0;
int initial_gid = 0;
BOOL share_mode_pending = False;
/* have I done a become_user? */
static struct {
int cnum, uid;
} last_user;
/* the last message the was processed */
int last_message = -1;
@ -1373,8 +1364,6 @@ int write_file(int fnum,char *data,int n)
}
static int old_umask = 022;
/****************************************************************************
load parameters specific to a connection/service
****************************************************************************/
@ -1419,261 +1408,6 @@ BOOL become_service(int cnum,BOOL do_chdir)
}
/****************************************************************************
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)
#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);
}
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)
#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);
}
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
****************************************************************************/
static 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"));
last_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 ngroups;
gid_t *groups;
if (last_user.cnum == cnum && last_user.uid == uid) {
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;
groups = Connections[cnum].groups;
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;
groups = vuser->user_groups;
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 (ngroups > 0)
if (setgroups(ngroups,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);
last_user.cnum = cnum;
last_user.uid = uid;
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 (last_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);
#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
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()));
last_user.cnum = -1;
return(True);
}
/****************************************************************************
find a service entry
****************************************************************************/
@ -3677,8 +3411,6 @@ void process(void )
}
#endif
last_user.cnum = -1;
while (True)
{
int32 len;
@ -3922,22 +3654,7 @@ int main(int argc,char *argv[])
umask(0777 & ~DEF_CREATE_MASK);
initial_uid = geteuid();
initial_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();
init_uid();
/* this is for people who can't start the program correctly */
while (argc > 1 && (*argv[1] != '-'))
@ -3999,8 +3716,6 @@ int main(int argc,char *argv[])
DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
GetWd(OriginalDir);
#ifndef NO_GETRLIMIT
#ifdef RLIMIT_NOFILE
{

View File

@ -44,53 +44,54 @@ static void close_fds(void)
This is a wrapper around the system call to allow commands to run correctly
as non root from a program which is switching between root and non-root
It takes one argument as argv[1] and runs it after becoming a non-root
user
*/
It takes 3 arguments as uid,gid,command and runs command after
becoming a non-root user */
int main(int argc,char *argv[])
{
int uid,gid;
close_fds();
if (getuid() != geteuid())
{
int uid,gid;
if (getuid() == 0)
uid = geteuid();
else
uid = getuid();
if (getgid() == 0)
gid = getegid();
else
gid = getgid();
if (argc != 4) exit(2);
uid = atoi(argv[1]);
gid = atoi(argv[2]);
/* first become root - we may need to do this in order to lose
our privilages! */
#ifdef USE_SETRES
setresgid(0,0,0);
setresuid(0,0,0);
setresgid(gid,gid,gid);
setresuid(uid,uid,uid);
setresgid(0,0,0);
setresuid(0,0,0);
#else
setuid(0);
seteuid(0);
setgid(gid);
setegid(gid);
setuid(uid);
seteuid(uid);
setuid(0);
seteuid(0);
#endif
if (getuid() != uid)
return(3);
}
#ifdef USE_SETFS
setfsuid(uid);
setfsgid(gid);
#endif
#ifdef USE_SETRES
setresgid(gid,gid,gid);
setresuid(uid,uid,uid);
#else
setgid(gid);
setegid(gid);
setuid(uid);
seteuid(uid);
#endif
/* paranoia :-) */
if (getuid() != uid)
return(3);
if (geteuid() != getuid())
return(1);
if (argc < 2)
return(2);
return(4);
/* this is to make sure that the system() call doesn't run forever */
alarm(30);
return(system(argv[1]));
return(system(argv[3]));
}

364
source3/smbd/uid.c Normal file
View File

@ -0,0 +1,364 @@
/*
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;
int current_uid;
int current_gid;
static pstring OriginalDir;
/* have I done a become_user? */
static struct {
int cnum, uid;
} last_user;
/****************************************************************************
initialise the uid routines
****************************************************************************/
void init_uid(void)
{
initial_uid = current_uid = geteuid();
initial_gid = current_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();
last_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_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_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"));
last_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 ngroups;
gid_t *groups;
if (last_user.cnum == cnum && last_user.uid == uid) {
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;
groups = Connections[cnum].groups;
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;
groups = vuser->user_groups;
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 (ngroups > 0)
if (setgroups(ngroups,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);
last_user.cnum = cnum;
last_user.uid = uid;
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 (last_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_uid = initial_uid;
current_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()));
last_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_uid,current_gid,cmd,
outfile?outfile:"/dev/null");
DEBUG(5,("smbrun - running %s ",syscmd));
ret = system(syscmd);
DEBUG(5,("gave %d\n",ret));
return(ret);
}