- moved the uid handling to uid.c
authorAndrew Tridgell <tridge@samba.org>
Sat, 1 Jun 1996 15:25:30 +0000 (15:25 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sat, 1 Jun 1996 15:25:30 +0000 (15:25 +0000)
- added setfsuid() support (for Linux)
- started adding some of Lukes changes, just the loadparm and ipc ones
so far

source/include/includes.h
source/include/smb.h
source/lib/util.c
source/loadparm.h
source/param/loadparm.c
source/smbd/ipc.c
source/smbd/server.c
source/smbd/smbrun.c
source/smbd/uid.c [new file with mode: 0644]

index dc1fe57e71a9897a3903f742c8cc66e270ed6e88..8b2821948c3cdcb3f580c1b95a030cfa9ca0ecc2 100644 (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
index 4d99529ef656a5c18a1cf92eab3962b1543f710c..3e38f4c37e421c2bd6a96da65c3960c4eb7b1d3a 100644 (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);
index 2ac64d06487357e50f239461c212ddda3c993de7..d2f03835326d696d3f9992df759b0fb1b73127f5 100644 (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
 
index 143c8a2fcab613be2a50794a291db6a7b60dbe7a..879ff25e67572795d6efff7c59f171ce8dbfa8e2 100644 (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);
index e7b9d2d9b8f1b219010ba1ea904fa976f7b75870..3426a4022c44e2e456c801299ef22d73426a6115 100644 (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)
index 3b2c55dc46b2121518adf9f8bb07ec4e0f25efbb..25979d72f5b914e8c857bcf653b748bb9881efc6 100644 (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;
index 3140d3ff84c6c8afa6018db0bc1ce8b0e05cc353..b8e3cba61c2eb03efb5707a447f28e951733dae1 100644 (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
   {
index df12ae1f85c271987e7efdcb43f9d8cf4ad61b76..6c9ba52b8b65b6d13df4d5f1353b9eaf1a967bfd 100644 (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
 
-  if (geteuid() != getuid())
-    return(1);
 
-  if (argc < 2)
-    return(2);
+  /* paranoia :-) */
+  if (getuid() != uid)
+    return(3);
+
+  if (geteuid() != getuid())
+    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]));
 }
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
new file mode 100644 (file)
index 0000000..f287c73
--- /dev/null
@@ -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);
+}
+
+