return "/tmp";
}
-
-
-/****************************************************************************
-prompte a dptr (to make it recently used)
-****************************************************************************/
-static void array_promote(char *array,int elsize,int element)
-{
- char *p;
- if (element == 0)
- return;
-
- p = (char *)malloc(elsize);
-
- if (!p)
- {
- DEBUG(5,("Ahh! Can't malloc\n"));
- return;
- }
- memcpy(p,array + element * elsize, elsize);
- memmove(array + elsize,array,elsize*element);
- memcpy(array,p,elsize);
- free(p);
-}
-
/****************************************************************************
determine whether we are in the specified group
****************************************************************************/
}
+/****************************************************************************
+gets either a hex number (0xNNN) or decimal integer (NNN).
+****************************************************************************/
+uint32 get_number(const char *tmp)
+{
+ if (strnequal(tmp, "0x", 2))
+ {
+ return strtoul(tmp, (char**)NULL, 16);
+ }
+ else
+ {
+ return strtoul(tmp, (char**)NULL, 10);
+ }
+}
+
/****************************************************************************
like atoi but gets the value up to the separater character
****************************************************************************/
return NULL;
}
- (*n) = atoi(p);
+ (*n) = (int)get_number(p);
+
+ if (strnequal(p, "0x", 2))
+ {
+ p += 2;
+ }
while ((*p) && isdigit(*p))
{
return p;
}
+uint32 *add_num_to_list(uint32 **num, int *count, int val)
+{
+ (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
+ if ((*num) == NULL)
+ {
+ return NULL;
+ }
+ (*num)[(*count)] = val;
+ (*count)++;
+
+ return (*num);
+}
+
/*************************************************************************
reads a list of numbers
*************************************************************************/
while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
{
- (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
- if ((*num) == NULL)
+ if (add_num_to_list(num, count, val) == NULL)
{
return NULL;
}
- (*num)[(*count)] = val;
- (*count)++;
p++;
}
SMB_STRUCT_STAT st;
if (!sbuf) sbuf = &st;
- if (dos_stat(fname,sbuf) != 0)
+ if (sys_stat(fname,sbuf) != 0)
return(False);
return(S_ISREG(sbuf->st_mode));
}
+/*******************************************************************
+ rename a unix file
+********************************************************************/
+int file_rename(char *from, char *to)
+{
+ int rcode = rename (from, to);
+
+ if (errno == EXDEV)
+ {
+ /* Rename across filesystems needed. */
+ rcode = copy_reg (from, to);
+ }
+ return rcode;
+}
+
/*******************************************************************
check a files mod time
********************************************************************/
{
SMB_STRUCT_STAT st;
- if (dos_stat(fname,&st) != 0)
+ if (sys_stat(fname,&st) != 0)
return(0);
return(st.st_mtime);
if (!st) st = &st2;
- if (dos_stat(dname,st) != 0)
+ if (sys_stat(dname,st) != 0)
return(False);
ret = S_ISDIR(st->st_mode);
{
SMB_STRUCT_STAT buf;
buf.st_size = 0;
- dos_stat(file_name,&buf);
+ if(sys_stat(file_name,&buf) != 0)
+ return (SMB_OFF_T)-1;
return(buf.st_size);
}
return(attrstr);
}
-
-
/****************************************************************************
make a file into unix format
****************************************************************************/
trim_string(s,NULL,"/..");
}
-
-/*******************************************************************
-a wrapper for the normal chdir() function
-********************************************************************/
-int ChDir(char *path)
-{
- int res;
- static pstring LastDir="";
-
- if (strcsequal(path,".")) return(0);
-
- if (*path == '/' && strcsequal(LastDir,path)) return(0);
- DEBUG(3,("chdir to %s\n",path));
- res = dos_chdir(path);
- if (!res)
- pstrcpy(LastDir,path);
- return(res);
-}
-
-/* number of list structures for a caching GetWd function. */
-#define MAX_GETWDCACHE (50)
-
-struct
-{
- SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
- SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
- char *text; /* The pathname in DOS format. */
- BOOL valid;
-} ino_list[MAX_GETWDCACHE];
-
-BOOL use_getwd_cache=True;
-
-/*******************************************************************
- return the absolute current directory path - given a UNIX pathname.
- Note that this path is returned in DOS format, not UNIX
- format.
-********************************************************************/
-char *GetWd(char *str)
-{
- pstring s;
- static BOOL getwd_cache_init = False;
- SMB_STRUCT_STAT st, st2;
- int i;
-
- *s = 0;
-
- if (!use_getwd_cache)
- return(dos_getwd(str));
-
- /* init the cache */
- if (!getwd_cache_init)
- {
- getwd_cache_init = True;
- for (i=0;i<MAX_GETWDCACHE;i++)
- {
- string_init(&ino_list[i].text,"");
- ino_list[i].valid = False;
- }
- }
-
- /* Get the inode of the current directory, if this doesn't work we're
- in trouble :-) */
-
- if (dos_stat(".",&st) == -1)
- {
- DEBUG(0,("Very strange, couldn't stat \".\"\n"));
- return(dos_getwd(str));
- }
-
-
- for (i=0; i<MAX_GETWDCACHE; i++)
- if (ino_list[i].valid)
- {
-
- /* If we have found an entry with a matching inode and dev number
- then find the inode number for the directory in the cached string.
- If this agrees with that returned by the stat for the current
- directory then all is o.k. (but make sure it is a directory all
- the same...) */
-
- if (st.st_ino == ino_list[i].inode &&
- st.st_dev == ino_list[i].dev)
- {
- if (dos_stat(ino_list[i].text,&st2) == 0)
- {
- if (st.st_ino == st2.st_ino &&
- st.st_dev == st2.st_dev &&
- (st2.st_mode & S_IFMT) == S_IFDIR)
- {
- pstrcpy (str, ino_list[i].text);
-
- /* promote it for future use */
- array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
- return (str);
- }
- else
- {
- /* If the inode is different then something's changed,
- scrub the entry and start from scratch. */
- ino_list[i].valid = False;
- }
- }
- }
- }
-
-
- /* We don't have the information to hand so rely on traditional methods.
- The very slow getcwd, which spawns a process on some systems, or the
- not quite so bad getwd. */
-
- if (!dos_getwd(s))
- {
- DEBUG(0,("Getwd failed, errno %s\n",strerror(errno)));
- return (NULL);
- }
-
- pstrcpy(str,s);
-
- DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
-
- /* add it to the cache */
- i = MAX_GETWDCACHE - 1;
- string_set(&ino_list[i].text,s);
- ino_list[i].dev = st.st_dev;
- ino_list[i].inode = st.st_ino;
- ino_list[i].valid = True;
-
- /* put it at the top of the list */
- array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
-
- return (str);
-}
-
-
-
/*******************************************************************
reduce a file name, removing .. elements and checking that
it is below dir in the heirachy. This uses GetWd() and so must be run
widelinks are allowed if widelinks is true
********************************************************************/
+
BOOL reduce_name(char *s,char *dir,BOOL widelinks)
{
#ifndef REDUCE_PATHS
if (!p)
return(True);
- if (!GetWd(wd))
+ if (!dos_GetWd(wd))
{
DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
return(False);
}
- if (ChDir(dir) != 0)
+ if (dos_ChDir(dir) != 0)
{
DEBUG(0,("couldn't chdir to %s\n",dir));
return(False);
}
- if (!GetWd(dir2))
+ if (!dos_GetWd(dir2))
{
DEBUG(0,("couldn't getwd for %s\n",dir));
- ChDir(wd);
+ dos_ChDir(wd);
return(False);
}
*p = '/';
}
- if (ChDir(base_name) != 0)
+ if (dos_ChDir(base_name) != 0)
{
- ChDir(wd);
+ dos_ChDir(wd);
DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
return(False);
}
- if (!GetWd(newname))
+ if (!dos_GetWd(newname))
{
- ChDir(wd);
+ dos_ChDir(wd);
DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
return(False);
}
}
{
- int l = strlen(dir2);
+ size_t l = strlen(dir2);
if (dir2[l-1] == '/')
l--;
if (strncmp(newname,dir2,l) != 0)
{
- ChDir(wd);
+ dos_ChDir(wd);
DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
return(False);
}
pstrcpy(s,newname);
}
- ChDir(wd);
+ dos_ChDir(wd);
if (strlen(s) == 0)
pstrcpy(s,"./");
/* try and use up these file descriptors, so silly
library routines writing to stdout etc won't cause havoc */
for (i=0;i<3;i++) {
- fd = open("/dev/null",O_RDWR,0);
- if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
+ fd = sys_open("/dev/null",O_RDWR,0);
+ if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
if (fd < 0) {
DEBUG(0,("Can't open /dev/null\n"));
return;
setsid();
#elif defined(TIOCNOTTY)
{
- int i = open("/dev/tty", O_RDWR);
+ int i = sys_open("/dev/tty", O_RDWR, 0);
if (i != -1) {
ioctl(i, (int) TIOCNOTTY, (char *)0);
close(i);
{
char *p, *s, *home;
- for (s=str; (p=strchr(s, '%'));s=p) {
- switch (*(p+1)) {
- case 'H':
- if ((home = get_home_dir(conn->user))) {
- string_sub(p,"%H",home);
- } else {
- p += 2;
- }
- break;
-
- case 'P':
- string_sub(p,"%P",conn->connectpath);
- break;
-
- case 'S':
- string_sub(p,"%S",
- lp_servicename(SNUM(conn)));
- break;
-
- case 'g':
- string_sub(p,"%g",
- gidtoname(conn->gid));
- break;
- case 'u':
- string_sub(p,"%u",conn->user);
- break;
-
+ for (s=str; (p=strchr(s, '%'));s=p)
+ {
+ switch (*(p+1))
+ {
+ case 'H':
+ if ((home = get_home_dir(conn->user)) != NULL) {
+ string_sub(p,"%H",home);
+ } else {
+ p += 2;
+ }
+ break;
+
/* Patch from jkf@soton.ac.uk Left the %N (NIS
* server name) in standard_sub_basic as it is
* a feature for logon servers, hence uses the
* here as it is used instead of the default
* "path =" string in [homes] and so needs the
* service name, not the username. */
- case 'p':
- string_sub(p,"%p",
- automount_path(lp_servicename(SNUM(conn))));
- break;
- case '\0':
- p++;
- break; /* don't run off the end of the string
- */
-
- default: p+=2;
- break;
+ case 'p': string_sub(p,"%p", automount_path(lp_servicename(SNUM(conn)))); break;
+ case 'P': string_sub(p,"%P",conn->connectpath); break;
+ case 'S': string_sub(p,"%S", lp_servicename(SNUM(conn))); break;
+ case 'g': string_sub(p,"%g", gidtoname(conn->gid)); break;
+ case 'u': string_sub(p,"%u", conn->user); break;
+
+ case '\0': p++; break; /* don't run off the end of the string */
+ default : p+=2; break;
}
}
a wrapper for gethostbyname() that tries with all lower and all upper case
if the initial name fails
****************************************************************************/
-struct hostent *Get_Hostbyname(char *name)
+struct hostent *Get_Hostbyname(const char *name)
{
char *name2 = strdup(name);
struct hostent *ret;
}
+/****************************************************************************
+Setup the groups a user belongs to.
+****************************************************************************/
+int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups)
+{
+ int i,ngroups;
+ gid_t grp = 0;
+ gid_t *groups = NULL;
+
+ if (-1 == initgroups(user,gid))
+ {
+ if (getuid() == 0)
+ {
+ DEBUG(0,("Unable to initgroups!\n"));
+ if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
+ {
+ DEBUG(0,("This is probably a problem with the account %s\n", user));
+ }
+ }
+ return -1;
+ }
+
+ ngroups = sys_getgroups(0,&grp);
+ if (ngroups <= 0)
+ {
+ ngroups = 32;
+ }
+
+ if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL)
+ {
+ DEBUG(0,("get_unixgroups malloc fail !\n"));
+ return -1;
+ }
+
+ ngroups = sys_getgroups(ngroups,groups);
+
+ (*p_ngroups) = ngroups;
+ (*p_groups) = groups;
+
+ DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) );
+ for (i = 0; i < ngroups; i++ )
+ {
+ DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
+ }
+ DEBUG( 3, ( "\n" ) );
+
+ return 0;
+}
+
/*******************************************************************
turn a uid into a user name
********************************************************************/
return(name);
}
+/*******************************************************************
+turn a group name into a gid
+********************************************************************/
+
+BOOL nametogid(const char *name, gid_t *gid)
+{
+ struct group *grp = getgrnam(name);
+ if (grp)
+ {
+ *gid = grp->gr_gid;
+ return True;
+ }
+ else if (isdigit(name[0]))
+ {
+ *gid = (gid_t)get_number(name);
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+}
+
/*******************************************************************
turn a user name into a uid
********************************************************************/
-uid_t nametouid(const char *name)
+BOOL nametouid(const char *name, uid_t *uid)
{
- struct passwd *pass = getpwnam(name);
- if (pass) return(pass->pw_uid);
- return (uid_t)-1;
+ struct passwd *pass = Get_Pwnam(name, False);
+ if (pass)
+ {
+ *uid = pass->pw_uid;
+ return True;
+ }
+ else if (isdigit(name[0]))
+ {
+ *uid = (uid_t)get_number(name);
+ return True;
+ }
+ else
+ {
+ return False;
+ }
}
/*******************************************************************
/*******************************************************************
a readdir wrapper which just returns the file name
********************************************************************/
-char *readdirname(void *p)
+char *readdirname(DIR *p)
{
struct dirent *ptr;
char *dname;
{
static pstring buf;
memcpy(buf, dname, NAMLEN(ptr)+1);
- unix_to_dos(buf, True);
dname = buf;
}
int ret;
if(lp_ole_locking_compat()) {
- SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask = (mask2<<2);
/* make sure the count is reasonable, we might kill the lockd otherwise */
count &= ~mask;
if ((offset & mask) != 0)
offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
} else {
- SMB_OFF_T mask = ((SMB_OFF_T)0x8) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask = (mask2<<1);
SMB_OFF_T neg_mask = ~mask;
/* interpret negative counts as large numbers */
return True;
}
+
+/****************************************************************************
+ become the specified uid - permanently !
+****************************************************************************/
+BOOL become_user_permanently(uid_t uid, gid_t gid)
+{
+ /* now completely lose our privilages. This is a fairly paranoid
+ way of doing it, but it does work on all systems that I know of */
+
+#ifdef HAVE_SETRESUID
+ /*
+ * Firstly ensure all our uids are set to root.
+ */
+ setresgid(0,0,0);
+ setresuid(0,0,0);
+
+ /*
+ * Now ensure we change all our gids.
+ */
+ setresgid(gid,gid,gid);
+
+ /*
+ * Now ensure all the uids are the user.
+ */
+ setresuid(uid,uid,uid);
+#else
+ /*
+ * Firstly ensure all our uids are set to root.
+ */
+ setuid(0);
+ seteuid(0);
+
+ /*
+ * Now ensure we change all our gids.
+ */
+ setgid(gid);
+ setegid(gid);
+
+ /*
+ * Now ensure all the uids are the user.
+ */
+ setuid(uid);
+ seteuid(uid);
+#endif
+
+ if (getuid() != uid || geteuid() != uid ||
+ getgid() != gid || getegid() != gid) {
+ /* We failed to lose our privilages. */
+ return False;
+ }
+
+ return(True);
+}